parent
b92e95ee7f
commit
f37ce795a1
|
@ -1 +0,0 @@
|
|||
require 'zip/zip'
|
1146
lib/zip/ChangeLog
1146
lib/zip/ChangeLog
File diff suppressed because it is too large
Load Diff
162
lib/zip/NEWS
162
lib/zip/NEWS
|
@ -1,162 +0,0 @@
|
|||
= Version 0.9.4
|
||||
|
||||
Changed ZipOutputStream.put_next_entry signature (API CHANGE!). Now
|
||||
allows comment, extra field and compression method to be specified.
|
||||
|
||||
= Version 0.9.3
|
||||
|
||||
Fixed: Added ZipEntry::name_encoding which retrieves the character
|
||||
encoding of the name and comment of the entry. Also added convenience
|
||||
methods ZipEntry::name_in(enc) and ZipEntry::comment_in(enc) for
|
||||
getting zip entry names and comments in a specified character
|
||||
encoding.
|
||||
|
||||
= Version 0.9.2
|
||||
|
||||
Fixed: Renaming an entry failed if the entry's new name was a
|
||||
different length than its old name. (Diego Barros)
|
||||
|
||||
= Version 0.9.1
|
||||
|
||||
Added symlink support and support for unix file permissions. Reduced
|
||||
memory usage during decompression.
|
||||
|
||||
New methods ZipFile::[follow_symlinks, restore_times, restore_permissions, restore_ownership].
|
||||
New methods ZipEntry::unix_perms, ZipInputStream::eof?.
|
||||
Added documentation and test for new ZipFile::extract.
|
||||
Added some of the API suggestions from sf.net #1281314.
|
||||
Applied patch for sf.net bug #1446926.
|
||||
Applied patch for sf.net bug #1459902.
|
||||
Rework ZipEntry and delegate classes.
|
||||
|
||||
= Version 0.5.12
|
||||
|
||||
Fixed problem with writing binary content to a ZipFile in MS Windows.
|
||||
|
||||
= Version 0.5.11
|
||||
|
||||
Fixed name clash file method copy_stream from fileutils.rb. Fixed
|
||||
problem with references to constant CHUNK_SIZE.
|
||||
ZipInputStream/AbstractInputStream read is now buffered like ruby IO's
|
||||
read method, which means that read and gets etc can be mixed. The
|
||||
unbuffered read method has been renamed to sysread.
|
||||
|
||||
= Version 0.5.10
|
||||
|
||||
Fixed method name resolution problem with FileUtils::copy_stream and
|
||||
IOExtras::copy_stream.
|
||||
|
||||
= Version 0.5.9
|
||||
|
||||
Fixed serious memory consumption issue
|
||||
|
||||
= Version 0.5.8
|
||||
|
||||
Fixed install script.
|
||||
|
||||
= Version 0.5.7
|
||||
|
||||
install.rb no longer assumes it is being run from the toplevel source
|
||||
dir. Directory structure changed to reflect common ruby library
|
||||
project structure. Migrated from RubyUnit to Test::Unit format. Now
|
||||
uses Rake to build source packages and gems and run unit tests.
|
||||
|
||||
= Version 0.5.6
|
||||
|
||||
Fix for FreeBSD 4.9 which returns Errno::EFBIG instead of
|
||||
Errno::EINVAL for some invalid seeks. Fixed 'version needed to
|
||||
extract'-field incorrect in local headers.
|
||||
|
||||
= Version 0.5.5
|
||||
|
||||
Fix for a problem with writing zip files that concerns only ruby 1.8.1.
|
||||
|
||||
= Version 0.5.4
|
||||
|
||||
Significantly reduced memory footprint when modifying zip files.
|
||||
|
||||
= Version 0.5.3
|
||||
|
||||
Added optimization to avoid decompressing and recompressing individual
|
||||
entries when modifying a zip archive.
|
||||
|
||||
= Version 0.5.2
|
||||
|
||||
Fixed ZipFile corruption bug in ZipFile class. Added basic unix
|
||||
extra-field support.
|
||||
|
||||
= Version 0.5.1
|
||||
|
||||
Fixed ZipFile.get_output_stream bug.
|
||||
|
||||
= Version 0.5.0
|
||||
|
||||
List of changes:
|
||||
* Ruby 1.8.0 and ruby-zlib 0.6.0 compatibility
|
||||
* Changed method names from camelCase to rubys underscore style.
|
||||
* Installs to zip/ subdir instead of directly to site_ruby
|
||||
* Added ZipFile.directory and ZipFile.file - each method return an
|
||||
object that can be used like Dir and File only for the contents of the
|
||||
zip file.
|
||||
* Added sample application zipfind which works like Find.find, only
|
||||
Zip::ZipFind.find traverses into zip archives too.
|
||||
|
||||
Bug fixes:
|
||||
* AbstractInputStream.each_line with non-default separator
|
||||
|
||||
|
||||
= Version 0.5.0a
|
||||
|
||||
Source reorganized. Added ziprequire, which can be used to load ruby
|
||||
modules from a zip file, in a fashion similar to jar files in
|
||||
Java. Added gtkRubyzip, another sample application. Implemented
|
||||
ZipInputStream.lineno and ZipInputStream.rewind
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Read and write date and time information correctly for zip entries.
|
||||
* Fixed read() using separate buffer, causing mix of gets/readline/read to
|
||||
cause problems.
|
||||
|
||||
= Version 0.4.2
|
||||
|
||||
Performance optimizations. Test suite runs in half the time.
|
||||
|
||||
= Version 0.4.1
|
||||
|
||||
Windows compatibility fixes.
|
||||
|
||||
= Version 0.4.0
|
||||
|
||||
Zip::ZipFile is now mutable and provides a more convenient way of
|
||||
modifying zip archives than Zip::ZipOutputStream. Operations for
|
||||
adding, extracting, renaming, replacing and removing entries to zip
|
||||
archives are now available.
|
||||
|
||||
Runs without warnings with -w switch.
|
||||
|
||||
Install script install.rb added.
|
||||
|
||||
|
||||
= Version 0.3.1
|
||||
|
||||
Rudimentary support for writing zip archives.
|
||||
|
||||
|
||||
= Version 0.2.2
|
||||
|
||||
Fixed and extended unit test suite. Updated to work with ruby/zlib
|
||||
0.5. It doesn't work with earlier versions of ruby/zlib.
|
||||
|
||||
|
||||
= Version 0.2.0
|
||||
|
||||
Class ZipFile added. Where ZipInputStream is used to read the
|
||||
individual entries in a zip file, ZipFile reads the central directory
|
||||
in the zip archive, so you can get to any entry in the zip archive
|
||||
without having to skipping through all the preceeding entries.
|
||||
|
||||
|
||||
= Version 0.1.0
|
||||
|
||||
First working version of ZipInputStream.
|
|
@ -1,72 +0,0 @@
|
|||
= rubyzip
|
||||
|
||||
rubyzip is a ruby library for reading and writing zip files.
|
||||
|
||||
= Install
|
||||
|
||||
If you have rubygems you can install rubyzip directly from the gem
|
||||
repository
|
||||
|
||||
gem install rubyzip
|
||||
|
||||
Otherwise obtain the source (see below) and run
|
||||
|
||||
ruby install.rb
|
||||
|
||||
To run the unit tests you need to have test::unit installed
|
||||
|
||||
rake test
|
||||
|
||||
|
||||
= Documentation
|
||||
|
||||
There is more than one way to access or create a zip archive with
|
||||
rubyzip. The basic API is modeled after the classes in
|
||||
java.util.zip from the Java SDK. This means there are classes such
|
||||
as Zip::ZipInputStream, Zip::ZipOutputStream and
|
||||
Zip::ZipFile. Zip::ZipInputStream provides a basic interface for
|
||||
iterating through the entries in a zip archive and reading from the
|
||||
entries in the same way as from a regular File or IO
|
||||
object. ZipOutputStream is the corresponding basic output
|
||||
facility. Zip::ZipFile provides a mean for accessing the archives
|
||||
central directory and provides means for accessing any entry without
|
||||
having to iterate through the archive. Unlike Java's
|
||||
java.util.zip.ZipFile rubyzip's Zip::ZipFile is mutable, which means
|
||||
it can be used to change zip files as well.
|
||||
|
||||
Another way to access a zip archive with rubyzip is to use rubyzip's
|
||||
Zip::ZipFileSystem API. Using this API files can be read from and
|
||||
written to the archive in much the same manner as ruby's builtin
|
||||
classes allows files to be read from and written to the file system.
|
||||
|
||||
rubyzip also features the
|
||||
zip/ziprequire.rb[link:files/lib/zip/ziprequire_rb.html] module which
|
||||
allows ruby to load ruby modules from zip archives.
|
||||
|
||||
For details about the specific behaviour of classes and methods refer
|
||||
to the test suite. Finally you can generate the rdoc documentation or
|
||||
visit http://rubyzip.sourceforge.net.
|
||||
|
||||
= License
|
||||
|
||||
rubyzip is distributed under the same license as ruby. See
|
||||
http://www.ruby-lang.org/en/LICENSE.txt
|
||||
|
||||
|
||||
= Website and Project Home
|
||||
|
||||
http://rubyzip.sourceforge.net
|
||||
|
||||
http://sourceforge.net/projects/rubyzip
|
||||
|
||||
== Download (tarballs and gems)
|
||||
|
||||
http://sourceforge.net/project/showfiles.php?group_id=43107&package_id=35377
|
||||
|
||||
= Authors
|
||||
|
||||
Thomas Sondergaard (thomas at sondergaard.cc)
|
||||
|
||||
Technorama Ltd. (oss-ruby-zip at technorama.net)
|
||||
|
||||
extra-field support contributed by Tatsuki Sugiura (sugi at nemui.org)
|
16
lib/zip/TODO
16
lib/zip/TODO
|
@ -1,16 +0,0 @@
|
|||
|
||||
* ZipInputStream: Support zip-files with trailing data descriptors
|
||||
* Adjust rdoc stylesheet to advertise inherited methods if possible
|
||||
* Suggestion: Add ZipFile/ZipInputStream example that demonstrates extracting all entries.
|
||||
* Suggestion: ZipFile#extract destination should default to "."
|
||||
* Suggestion: ZipEntry should have extract(), get_input_stream() methods etc
|
||||
* SUggestion: ZipInputStream/ZipOutputStream should accept an IO object in addition to a filename.
|
||||
* (is buffering used anywhere with write?)
|
||||
* Inflater.sysread should pass the buffer to produce_input.
|
||||
* Implement ZipFsDir.glob
|
||||
* ZipFile.checkIntegrity method
|
||||
* non-MSDOS permission attributes
|
||||
** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2"
|
||||
* Packager version, required unpacker version in zip headers
|
||||
** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2"
|
||||
* implement storing attributes and ownership information
|
|
@ -1,165 +0,0 @@
|
|||
module IOExtras #:nodoc:
|
||||
|
||||
CHUNK_SIZE = 131072
|
||||
|
||||
RANGE_ALL = 0..-1
|
||||
|
||||
def self.copy_stream(ostream, istream)
|
||||
s = ''
|
||||
ostream.write(istream.read(CHUNK_SIZE, s)) until istream.eof?
|
||||
end
|
||||
|
||||
def self.copy_stream_n(ostream, istream, nbytes)
|
||||
s = ''
|
||||
toread = nbytes
|
||||
while (toread > 0 && ! istream.eof?)
|
||||
tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
|
||||
ostream.write(istream.read(tr, s))
|
||||
toread -= tr
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Implements kind_of? in order to pretend to be an IO object
|
||||
module FakeIO
|
||||
def kind_of?(object)
|
||||
object == IO || super
|
||||
end
|
||||
end
|
||||
|
||||
# Implements many of the convenience methods of IO
|
||||
# such as gets, getc, readline and readlines
|
||||
# depends on: input_finished?, produce_input and read
|
||||
module AbstractInputStream
|
||||
include Enumerable
|
||||
include FakeIO
|
||||
|
||||
def initialize
|
||||
super
|
||||
@lineno = 0
|
||||
@outputBuffer = ""
|
||||
end
|
||||
|
||||
attr_accessor :lineno
|
||||
|
||||
def read(numberOfBytes = nil, buf = nil)
|
||||
tbuf = nil
|
||||
|
||||
if @outputBuffer.length > 0
|
||||
if numberOfBytes <= @outputBuffer.length
|
||||
tbuf = @outputBuffer.slice!(0, numberOfBytes)
|
||||
else
|
||||
numberOfBytes -= @outputBuffer.length if (numberOfBytes)
|
||||
rbuf = sysread(numberOfBytes, buf)
|
||||
tbuf = @outputBuffer
|
||||
tbuf << rbuf if (rbuf)
|
||||
@outputBuffer = ""
|
||||
end
|
||||
else
|
||||
tbuf = sysread(numberOfBytes, buf)
|
||||
end
|
||||
|
||||
return nil unless (tbuf)
|
||||
|
||||
if buf
|
||||
buf.replace(tbuf)
|
||||
else
|
||||
buf = tbuf
|
||||
end
|
||||
|
||||
buf
|
||||
end
|
||||
|
||||
def readlines(aSepString = $/)
|
||||
retVal = []
|
||||
each_line(aSepString) { |line| retVal << line }
|
||||
return retVal
|
||||
end
|
||||
|
||||
def gets(aSepString=$/)
|
||||
@lineno = @lineno.next
|
||||
return read if aSepString == nil
|
||||
aSepString="#{$/}#{$/}" if aSepString == ""
|
||||
|
||||
bufferIndex=0
|
||||
while ((matchIndex = @outputBuffer.index(aSepString, bufferIndex)) == nil)
|
||||
bufferIndex=@outputBuffer.length
|
||||
if input_finished?
|
||||
return @outputBuffer.empty? ? nil : flush
|
||||
end
|
||||
@outputBuffer << produce_input
|
||||
end
|
||||
sepIndex=matchIndex + aSepString.length
|
||||
return @outputBuffer.slice!(0...sepIndex)
|
||||
end
|
||||
|
||||
def flush
|
||||
retVal=@outputBuffer
|
||||
@outputBuffer=""
|
||||
return retVal
|
||||
end
|
||||
|
||||
def readline(aSepString = $/)
|
||||
retVal = gets(aSepString)
|
||||
raise EOFError if retVal == nil
|
||||
return retVal
|
||||
end
|
||||
|
||||
def each_line(aSepString = $/)
|
||||
while true
|
||||
yield readline(aSepString)
|
||||
end
|
||||
rescue EOFError
|
||||
end
|
||||
|
||||
alias_method :each, :each_line
|
||||
end
|
||||
|
||||
|
||||
# Implements many of the output convenience methods of IO.
|
||||
# relies on <<
|
||||
module AbstractOutputStream
|
||||
include FakeIO
|
||||
|
||||
def write(data)
|
||||
self << data
|
||||
data.to_s.length
|
||||
end
|
||||
|
||||
|
||||
def print(*params)
|
||||
self << params.join << $\.to_s
|
||||
end
|
||||
|
||||
def printf(aFormatString, *params)
|
||||
self << sprintf(aFormatString, *params)
|
||||
end
|
||||
|
||||
def putc(anObject)
|
||||
self << case anObject
|
||||
when Fixnum then anObject.chr
|
||||
when String then anObject
|
||||
else raise TypeError, "putc: Only Fixnum and String supported"
|
||||
end
|
||||
anObject
|
||||
end
|
||||
|
||||
def puts(*params)
|
||||
params << "\n" if params.empty?
|
||||
params.flatten.each {
|
||||
|element|
|
||||
val = element.to_s
|
||||
self << val
|
||||
self << "\n" unless val[-1,1] == "\n"
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end # IOExtras namespace module
|
||||
|
||||
|
||||
|
||||
# Copyright (C) 2002-2004 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,69 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$: << "../lib"
|
||||
system("zip example.zip example.rb gtkRubyzip.rb")
|
||||
|
||||
require 'zip/zip'
|
||||
|
||||
####### Using ZipInputStream alone: #######
|
||||
|
||||
Zip::ZipInputStream.open("example.zip") {
|
||||
|zis|
|
||||
entry = zis.get_next_entry
|
||||
print "First line of '#{entry.name} (#{entry.size} bytes): "
|
||||
puts "'#{zis.gets.chomp}'"
|
||||
entry = zis.get_next_entry
|
||||
print "First line of '#{entry.name} (#{entry.size} bytes): "
|
||||
puts "'#{zis.gets.chomp}'"
|
||||
}
|
||||
|
||||
|
||||
####### Using ZipFile to read the directory of a zip file: #######
|
||||
|
||||
zf = Zip::ZipFile.new("example.zip")
|
||||
zf.each_with_index {
|
||||
|entry, index|
|
||||
|
||||
puts "entry #{index} is #{entry.name}, size = #{entry.size}, compressed size = #{entry.compressed_size}"
|
||||
# use zf.get_input_stream(entry) to get a ZipInputStream for the entry
|
||||
# entry can be the ZipEntry object or any object which has a to_s method that
|
||||
# returns the name of the entry.
|
||||
}
|
||||
|
||||
|
||||
####### Using ZipOutputStream to write a zip file: #######
|
||||
|
||||
Zip::ZipOutputStream.open("exampleout.zip") {
|
||||
|zos|
|
||||
zos.put_next_entry("the first little entry")
|
||||
zos.puts "Hello hello hello hello hello hello hello hello hello"
|
||||
|
||||
zos.put_next_entry("the second little entry")
|
||||
zos.puts "Hello again"
|
||||
|
||||
# Use rubyzip or your zip client of choice to verify
|
||||
# the contents of exampleout.zip
|
||||
}
|
||||
|
||||
####### Using ZipFile to change a zip file: #######
|
||||
|
||||
Zip::ZipFile.open("exampleout.zip") {
|
||||
|zf|
|
||||
zf.add("thisFile.rb", "example.rb")
|
||||
zf.rename("thisFile.rb", "ILikeThisName.rb")
|
||||
zf.add("Again", "example.rb")
|
||||
}
|
||||
|
||||
# Lets check
|
||||
Zip::ZipFile.open("exampleout.zip") {
|
||||
|zf|
|
||||
puts "Changed zip file contains: #{zf.entries.join(', ')}"
|
||||
zf.remove("Again")
|
||||
puts "Without 'Again': #{zf.entries.join(', ')}"
|
||||
}
|
||||
|
||||
# For other examples, look at zip.rb and ziptest.rb
|
||||
|
||||
# Copyright (C) 2002 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,33 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'zip/zipfilesystem'
|
||||
|
||||
EXAMPLE_ZIP = "filesystem.zip"
|
||||
|
||||
File.delete(EXAMPLE_ZIP) if File.exists?(EXAMPLE_ZIP)
|
||||
|
||||
Zip::ZipFile.open(EXAMPLE_ZIP, Zip::ZipFile::CREATE) {
|
||||
|zf|
|
||||
zf.file.open("file1.txt", "w") { |os| os.write "first file1.txt" }
|
||||
zf.dir.mkdir("dir1")
|
||||
zf.dir.chdir("dir1")
|
||||
zf.file.open("file1.txt", "w") { |os| os.write "second file1.txt" }
|
||||
puts zf.file.read("file1.txt")
|
||||
puts zf.file.read("../file1.txt")
|
||||
zf.dir.chdir("..")
|
||||
zf.file.open("file2.txt", "w") { |os| os.write "first file2.txt" }
|
||||
puts "Entries: #{zf.entries.join(', ')}"
|
||||
}
|
||||
|
||||
Zip::ZipFile.open(EXAMPLE_ZIP) {
|
||||
|zf|
|
||||
puts "Entries from reloaded zip: #{zf.entries.join(', ')}"
|
||||
}
|
||||
|
||||
# For other examples, look at zip.rb and ziptest.rb
|
||||
|
||||
# Copyright (C) 2003 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,86 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
require 'gtk'
|
||||
require 'zip/zip'
|
||||
|
||||
class MainApp < Gtk::Window
|
||||
def initialize
|
||||
super()
|
||||
set_usize(400, 256)
|
||||
set_title("rubyzip")
|
||||
signal_connect(Gtk::Window::SIGNAL_DESTROY) { Gtk.main_quit }
|
||||
|
||||
box = Gtk::VBox.new(false, 0)
|
||||
add(box)
|
||||
|
||||
@zipfile = nil
|
||||
@buttonPanel = ButtonPanel.new
|
||||
@buttonPanel.openButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
|
||||
show_file_selector
|
||||
}
|
||||
@buttonPanel.extractButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
|
||||
puts "Not implemented!"
|
||||
}
|
||||
box.pack_start(@buttonPanel, false, false, 0)
|
||||
|
||||
sw = Gtk::ScrolledWindow.new
|
||||
sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
|
||||
box.pack_start(sw, true, true, 0)
|
||||
|
||||
@clist = Gtk::CList.new(["Name", "Size", "Compression"])
|
||||
@clist.set_selection_mode(Gtk::SELECTION_BROWSE)
|
||||
@clist.set_column_width(0, 120)
|
||||
@clist.set_column_width(1, 120)
|
||||
@clist.signal_connect(Gtk::CList::SIGNAL_SELECT_ROW) {
|
||||
|w, row, column, event|
|
||||
@selected_row = row
|
||||
}
|
||||
sw.add(@clist)
|
||||
end
|
||||
|
||||
class ButtonPanel < Gtk::HButtonBox
|
||||
attr_reader :openButton, :extractButton
|
||||
def initialize
|
||||
super
|
||||
set_layout(Gtk::BUTTONBOX_START)
|
||||
set_spacing(0)
|
||||
@openButton = Gtk::Button.new("Open archive")
|
||||
@extractButton = Gtk::Button.new("Extract entry")
|
||||
pack_start(@openButton)
|
||||
pack_start(@extractButton)
|
||||
end
|
||||
end
|
||||
|
||||
def show_file_selector
|
||||
@fileSelector = Gtk::FileSelection.new("Open zip file")
|
||||
@fileSelector.show
|
||||
@fileSelector.ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
|
||||
open_zip(@fileSelector.filename)
|
||||
@fileSelector.destroy
|
||||
}
|
||||
@fileSelector.cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
|
||||
@fileSelector.destroy
|
||||
}
|
||||
end
|
||||
|
||||
def open_zip(filename)
|
||||
@zipfile = Zip::ZipFile.open(filename)
|
||||
@clist.clear
|
||||
@zipfile.each {
|
||||
|entry|
|
||||
@clist.append([ entry.name,
|
||||
entry.size.to_s,
|
||||
(100.0*entry.compressedSize/entry.size).to_s+"%" ])
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
mainApp = MainApp.new()
|
||||
|
||||
mainApp.show_all
|
||||
|
||||
Gtk.main
|
|
@ -1,101 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE=true
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'Qt'
|
||||
system('rbuic -o zipdialogui.rb zipdialogui.ui')
|
||||
require 'zipdialogui.rb'
|
||||
require 'zip/zip'
|
||||
|
||||
|
||||
|
||||
a = Qt::Application.new(ARGV)
|
||||
|
||||
class ZipDialog < ZipDialogUI
|
||||
|
||||
|
||||
def initialize()
|
||||
super()
|
||||
connect(child('add_button'), SIGNAL('clicked()'),
|
||||
self, SLOT('add_files()'))
|
||||
connect(child('extract_button'), SIGNAL('clicked()'),
|
||||
self, SLOT('extract_files()'))
|
||||
end
|
||||
|
||||
def zipfile(&proc)
|
||||
Zip::ZipFile.open(@zip_filename, &proc)
|
||||
end
|
||||
|
||||
def each(&proc)
|
||||
Zip::ZipFile.foreach(@zip_filename, &proc)
|
||||
end
|
||||
|
||||
def refresh()
|
||||
lv = child("entry_list_view")
|
||||
lv.clear
|
||||
each {
|
||||
|e|
|
||||
lv.insert_item(Qt::ListViewItem.new(lv, e.name, e.size.to_s))
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def load(zipfile)
|
||||
@zip_filename = zipfile
|
||||
refresh
|
||||
end
|
||||
|
||||
def add_files
|
||||
l = Qt::FileDialog.getOpenFileNames(nil, nil, self)
|
||||
zipfile {
|
||||
|zf|
|
||||
l.each {
|
||||
|path|
|
||||
zf.add(File.basename(path), path)
|
||||
}
|
||||
}
|
||||
refresh
|
||||
end
|
||||
|
||||
def extract_files
|
||||
selected_items = []
|
||||
unselected_items = []
|
||||
lv_item = entry_list_view.first_child
|
||||
while (lv_item)
|
||||
if entry_list_view.is_selected(lv_item)
|
||||
selected_items << lv_item.text(0)
|
||||
else
|
||||
unselected_items << lv_item.text(0)
|
||||
end
|
||||
lv_item = lv_item.next_sibling
|
||||
end
|
||||
puts "selected_items.size = #{selected_items.size}"
|
||||
puts "unselected_items.size = #{unselected_items.size}"
|
||||
items = selected_items.size > 0 ? selected_items : unselected_items
|
||||
puts "items.size = #{items.size}"
|
||||
|
||||
d = Qt::FileDialog.get_existing_directory(nil, self)
|
||||
if (!d)
|
||||
puts "No directory chosen"
|
||||
else
|
||||
zipfile { |zf| items.each { |e| zf.extract(e, File.join(d, e)) } }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
slots 'add_files()', 'extract_files()'
|
||||
end
|
||||
|
||||
if !ARGV[0]
|
||||
puts "usage: #{$0} zipname"
|
||||
exit
|
||||
end
|
||||
|
||||
zd = ZipDialog.new
|
||||
zd.load(ARGV[0])
|
||||
|
||||
a.mainWidget = zd
|
||||
zd.show()
|
||||
a.exec()
|
|
@ -1,13 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'zip/zip'
|
||||
|
||||
include Zip
|
||||
|
||||
ZipOutputStream.open('simple.zip') {
|
||||
|zos|
|
||||
ze = zos.put_next_entry 'entry.txt'
|
||||
zos.puts "Hello world"
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'zip/zip'
|
||||
require 'find'
|
||||
|
||||
module Zip
|
||||
module ZipFind
|
||||
def self.find(path, zipFilePattern = /\.zip$/i)
|
||||
Find.find(path) {
|
||||
|fileName|
|
||||
yield(fileName)
|
||||
if zipFilePattern.match(fileName) && File.file?(fileName)
|
||||
begin
|
||||
Zip::ZipFile.foreach(fileName) {
|
||||
|zipEntry|
|
||||
yield(fileName + File::SEPARATOR + zipEntry.to_s)
|
||||
}
|
||||
rescue Errno::EACCES => ex
|
||||
puts ex
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def self.find_file(path, fileNamePattern, zipFilePattern = /\.zip$/i)
|
||||
self.find(path, zipFilePattern) {
|
||||
|fileName|
|
||||
yield(fileName) if fileNamePattern.match(fileName)
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
module ZipFindConsoleRunner
|
||||
|
||||
PATH_ARG_INDEX = 0;
|
||||
FILENAME_PATTERN_ARG_INDEX = 1;
|
||||
ZIPFILE_PATTERN_ARG_INDEX = 2;
|
||||
|
||||
def self.run(args)
|
||||
check_args(args)
|
||||
Zip::ZipFind.find_file(args[PATH_ARG_INDEX],
|
||||
args[FILENAME_PATTERN_ARG_INDEX],
|
||||
args[ZIPFILE_PATTERN_ARG_INDEX]) {
|
||||
|fileName|
|
||||
report_entry_found fileName
|
||||
}
|
||||
end
|
||||
|
||||
def self.check_args(args)
|
||||
if (args.size != 3)
|
||||
usage
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
def self.usage
|
||||
puts "Usage: #{$0} PATH ZIPFILENAME_PATTERN FILNAME_PATTERN"
|
||||
end
|
||||
|
||||
def self.report_entry_found(fileName)
|
||||
puts fileName
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
ZipFindConsoleRunner.run(ARGV)
|
||||
end
|
|
@ -1,111 +0,0 @@
|
|||
unless Enumerable.method_defined?(:inject)
|
||||
module Enumerable #:nodoc:all
|
||||
def inject(n = 0)
|
||||
each { |value| n = yield(n, value) }
|
||||
n
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Enumerable #:nodoc:all
|
||||
# returns a new array of all the return values not equal to nil
|
||||
# This implementation could be faster
|
||||
def select_map(&aProc)
|
||||
map(&aProc).reject { |e| e.nil? }
|
||||
end
|
||||
end
|
||||
|
||||
unless Object.method_defined?(:object_id)
|
||||
class Object #:nodoc:all
|
||||
# Using object_id which is the new thing, so we need
|
||||
# to make that work in versions prior to 1.8.0
|
||||
alias object_id id
|
||||
end
|
||||
end
|
||||
|
||||
unless File.respond_to?(:read)
|
||||
class File # :nodoc:all
|
||||
# singleton method read does not exist in 1.6.x
|
||||
def self.read(fileName)
|
||||
open(fileName) { |f| f.read }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class String #:nodoc:all
|
||||
def starts_with(aString)
|
||||
rindex(aString, 0) == 0
|
||||
end
|
||||
|
||||
def ends_with(aString)
|
||||
index(aString, -aString.size)
|
||||
end
|
||||
|
||||
def ensure_end(aString)
|
||||
ends_with(aString) ? self : self + aString
|
||||
end
|
||||
|
||||
def lchop
|
||||
slice(1, length)
|
||||
end
|
||||
end
|
||||
|
||||
class Time #:nodoc:all
|
||||
|
||||
#MS-DOS File Date and Time format as used in Interrupt 21H Function 57H:
|
||||
#
|
||||
# Register CX, the Time:
|
||||
# Bits 0-4 2 second increments (0-29)
|
||||
# Bits 5-10 minutes (0-59)
|
||||
# bits 11-15 hours (0-24)
|
||||
#
|
||||
# Register DX, the Date:
|
||||
# Bits 0-4 day (1-31)
|
||||
# bits 5-8 month (1-12)
|
||||
# bits 9-15 year (four digit year minus 1980)
|
||||
|
||||
|
||||
def to_binary_dos_time
|
||||
(sec/2) +
|
||||
(min << 5) +
|
||||
(hour << 11)
|
||||
end
|
||||
|
||||
def to_binary_dos_date
|
||||
(day) +
|
||||
(month << 5) +
|
||||
((year - 1980) << 9)
|
||||
end
|
||||
|
||||
# Dos time is only stored with two seconds accuracy
|
||||
def dos_equals(other)
|
||||
to_i/2 == other.to_i/2
|
||||
end
|
||||
|
||||
def self.parse_binary_dos_format(binaryDosDate, binaryDosTime)
|
||||
second = 2 * ( 0b11111 & binaryDosTime)
|
||||
minute = ( 0b11111100000 & binaryDosTime) >> 5
|
||||
hour = (0b1111100000000000 & binaryDosTime) >> 11
|
||||
day = ( 0b11111 & binaryDosDate)
|
||||
month = ( 0b111100000 & binaryDosDate) >> 5
|
||||
year = ((0b1111111000000000 & binaryDosDate) >> 9) + 1980
|
||||
begin
|
||||
return Time.local(year, month, day, hour, minute, second)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Module #:nodoc:all
|
||||
def forward_message(forwarder, *messagesToForward)
|
||||
methodDefs = messagesToForward.map {
|
||||
|msg|
|
||||
"def #{msg}; #{forwarder}(:#{msg}); end"
|
||||
}
|
||||
module_eval(methodDefs.join("\n"))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,195 +0,0 @@
|
|||
#
|
||||
# tempfile - manipulates temporary files
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
require 'delegate'
|
||||
require 'tmpdir'
|
||||
|
||||
module BugFix #:nodoc:all
|
||||
|
||||
# A class for managing temporary files. This library is written to be
|
||||
# thread safe.
|
||||
class Tempfile < DelegateClass(File)
|
||||
MAX_TRY = 10
|
||||
@@cleanlist = []
|
||||
|
||||
# Creates a temporary file of mode 0600 in the temporary directory
|
||||
# whose name is basename.pid.n and opens with mode "w+". A Tempfile
|
||||
# object works just like a File object.
|
||||
#
|
||||
# If tmpdir is omitted, the temporary directory is determined by
|
||||
# Dir::tmpdir provided by 'tmpdir.rb'.
|
||||
# When $SAFE > 0 and the given tmpdir is tainted, it uses
|
||||
# /tmp. (Note that ENV values are tainted by default)
|
||||
def initialize(basename, tmpdir=Dir::tmpdir)
|
||||
if $SAFE > 0 and tmpdir.tainted?
|
||||
tmpdir = '/tmp'
|
||||
end
|
||||
|
||||
lock = nil
|
||||
n = failure = 0
|
||||
|
||||
begin
|
||||
Thread.critical = true
|
||||
|
||||
begin
|
||||
tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n)
|
||||
lock = tmpname + '.lock'
|
||||
n += 1
|
||||
end while @@cleanlist.include?(tmpname) or
|
||||
File.exist?(lock) or File.exist?(tmpname)
|
||||
|
||||
Dir.mkdir(lock)
|
||||
rescue
|
||||
failure += 1
|
||||
retry if failure < MAX_TRY
|
||||
raise "cannot generate tempfile `%s'" % tmpname
|
||||
ensure
|
||||
Thread.critical = false
|
||||
end
|
||||
|
||||
@data = [tmpname]
|
||||
@clean_proc = Tempfile.callback(@data)
|
||||
ObjectSpace.define_finalizer(self, @clean_proc)
|
||||
|
||||
@tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
|
||||
@tmpname = tmpname
|
||||
@@cleanlist << @tmpname
|
||||
@data[1] = @tmpfile
|
||||
@data[2] = @@cleanlist
|
||||
|
||||
super(@tmpfile)
|
||||
|
||||
# Now we have all the File/IO methods defined, you must not
|
||||
# carelessly put bare puts(), etc. after this.
|
||||
|
||||
Dir.rmdir(lock)
|
||||
end
|
||||
|
||||
# Opens or reopens the file with mode "r+".
|
||||
def open
|
||||
@tmpfile.close if @tmpfile
|
||||
@tmpfile = File.open(@tmpname, 'r+')
|
||||
@data[1] = @tmpfile
|
||||
__setobj__(@tmpfile)
|
||||
end
|
||||
|
||||
def _close # :nodoc:
|
||||
@tmpfile.close if @tmpfile
|
||||
@data[1] = @tmpfile = nil
|
||||
end
|
||||
protected :_close
|
||||
|
||||
# Closes the file. If the optional flag is true, unlinks the file
|
||||
# after closing.
|
||||
#
|
||||
# If you don't explicitly unlink the temporary file, the removal
|
||||
# will be delayed until the object is finalized.
|
||||
def close(unlink_now=false)
|
||||
if unlink_now
|
||||
close!
|
||||
else
|
||||
_close
|
||||
end
|
||||
end
|
||||
|
||||
# Closes and unlinks the file.
|
||||
def close!
|
||||
_close
|
||||
@clean_proc.call
|
||||
ObjectSpace.undefine_finalizer(self)
|
||||
end
|
||||
|
||||
# Unlinks the file. On UNIX-like systems, it is often a good idea
|
||||
# to unlink a temporary file immediately after creating and opening
|
||||
# it, because it leaves other programs zero chance to access the
|
||||
# file.
|
||||
def unlink
|
||||
# keep this order for thread safeness
|
||||
File.unlink(@tmpname) if File.exist?(@tmpname)
|
||||
@@cleanlist.delete(@tmpname) if @@cleanlist
|
||||
end
|
||||
alias delete unlink
|
||||
|
||||
if RUBY_VERSION > '1.8.0'
|
||||
def __setobj__(obj)
|
||||
@_dc_obj = obj
|
||||
end
|
||||
else
|
||||
def __setobj__(obj)
|
||||
@obj = obj
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the full path name of the temporary file.
|
||||
def path
|
||||
@tmpname
|
||||
end
|
||||
|
||||
# Returns the size of the temporary file. As a side effect, the IO
|
||||
# buffer is flushed before determining the size.
|
||||
def size
|
||||
if @tmpfile
|
||||
@tmpfile.flush
|
||||
@tmpfile.stat.size
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
alias length size
|
||||
|
||||
class << self
|
||||
def callback(data) # :nodoc:
|
||||
pid = $$
|
||||
lambda{
|
||||
if pid == $$
|
||||
path, tmpfile, cleanlist = *data
|
||||
|
||||
print "removing ", path, "..." if $DEBUG
|
||||
|
||||
tmpfile.close if tmpfile
|
||||
|
||||
# keep this order for thread safeness
|
||||
File.unlink(path) if File.exist?(path)
|
||||
cleanlist.delete(path) if cleanlist
|
||||
|
||||
print "done\n" if $DEBUG
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# If no block is given, this is a synonym for new().
|
||||
#
|
||||
# If a block is given, it will be passed tempfile as an argument,
|
||||
# and the tempfile will automatically be closed when the block
|
||||
# terminates. In this case, open() returns nil.
|
||||
def open(*args)
|
||||
tempfile = new(*args)
|
||||
|
||||
if block_given?
|
||||
begin
|
||||
yield(tempfile)
|
||||
ensure
|
||||
tempfile.close
|
||||
end
|
||||
|
||||
nil
|
||||
else
|
||||
tempfile
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end # module BugFix
|
||||
if __FILE__ == $0
|
||||
# $DEBUG = true
|
||||
f = Tempfile.new("foo")
|
||||
f.print("foo\n")
|
||||
f.close
|
||||
f.open
|
||||
p f.gets # => "foo\n"
|
||||
f.close!
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
require 'stdrubyexttest'
|
||||
require 'ioextrastest'
|
||||
require 'ziptest'
|
||||
require 'zipfilesystemtest'
|
||||
require 'ziprequiretest'
|
|
@ -1,46 +0,0 @@
|
|||
|
||||
AUTOMAKE_OPTIONS = gnu
|
||||
|
||||
EXTRA_DIST = test.zip
|
||||
|
||||
CXXFLAGS= -g
|
||||
|
||||
noinst_LIBRARIES = libzipios.a
|
||||
|
||||
bin_PROGRAMS = test_zip test_izipfilt test_izipstream
|
||||
# test_flist
|
||||
|
||||
libzipios_a_SOURCES = backbuffer.h fcol.cpp fcol.h \
|
||||
fcol_common.h fcolexceptions.cpp fcolexceptions.h \
|
||||
fileentry.cpp fileentry.h flist.cpp \
|
||||
flist.h flistentry.cpp flistentry.h \
|
||||
flistscanner.h ifiltstreambuf.cpp ifiltstreambuf.h \
|
||||
inflatefilt.cpp inflatefilt.h izipfilt.cpp \
|
||||
izipfilt.h izipstream.cpp izipstream.h \
|
||||
zipfile.cpp zipfile.h ziphead.cpp \
|
||||
ziphead.h flistscanner.ll
|
||||
|
||||
# test_flist_SOURCES = test_flist.cpp
|
||||
|
||||
test_izipfilt_SOURCES = test_izipfilt.cpp
|
||||
|
||||
test_izipstream_SOURCES = test_izipstream.cpp
|
||||
|
||||
test_zip_SOURCES = test_zip.cpp
|
||||
|
||||
# Notice that libzipios.a is not specified as -L. -lzipios
|
||||
# If it was, automake would not include it as a dependency.
|
||||
|
||||
# test_flist_LDADD = libzipios.a
|
||||
|
||||
test_izipfilt_LDADD = libzipios.a -lz
|
||||
|
||||
test_zip_LDADD = libzipios.a -lz
|
||||
|
||||
test_izipstream_LDADD = libzipios.a -lz
|
||||
|
||||
|
||||
|
||||
flistscanner.cc : flistscanner.ll
|
||||
$(LEX) -+ -PFListScanner -o$@ $^
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
0.040244959211864
|
|
@ -1 +0,0 @@
|
|||
0.917381580665493
|
|
@ -1 +0,0 @@
|
|||
0.670572209005379
|
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
ABCDEF
|
Binary file not shown.
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
class NotZippedRuby
|
||||
def returnTrue
|
||||
true
|
||||
end
|
||||
end
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,160 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
class TestFiles
|
||||
RANDOM_ASCII_FILE1 = "data/generated/randomAscii1.txt"
|
||||
RANDOM_ASCII_FILE2 = "data/generated/randomAscii2.txt"
|
||||
RANDOM_ASCII_FILE3 = "data/generated/randomAscii3.txt"
|
||||
RANDOM_BINARY_FILE1 = "data/generated/randomBinary1.bin"
|
||||
RANDOM_BINARY_FILE2 = "data/generated/randomBinary2.bin"
|
||||
|
||||
EMPTY_TEST_DIR = "data/generated/emptytestdir"
|
||||
|
||||
ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ]
|
||||
BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ]
|
||||
TEST_DIRECTORIES = [ EMPTY_TEST_DIR ]
|
||||
TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten!
|
||||
|
||||
def TestFiles.create_test_files(recreate)
|
||||
if (recreate ||
|
||||
! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) }))
|
||||
|
||||
Dir.mkdir "data/generated" rescue Errno::EEXIST
|
||||
|
||||
ASCII_TEST_FILES.each_with_index {
|
||||
|filename, index|
|
||||
create_random_ascii(filename, 1E4 * (index+1))
|
||||
}
|
||||
|
||||
BINARY_TEST_FILES.each_with_index {
|
||||
|filename, index|
|
||||
create_random_binary(filename, 1E4 * (index+1))
|
||||
}
|
||||
|
||||
ensure_dir(EMPTY_TEST_DIR)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def TestFiles.create_random_ascii(filename, size)
|
||||
File.open(filename, "wb") {
|
||||
|file|
|
||||
while (file.tell < size)
|
||||
file << rand
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def TestFiles.create_random_binary(filename, size)
|
||||
File.open(filename, "wb") {
|
||||
|file|
|
||||
while (file.tell < size)
|
||||
file << [rand].pack("V")
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def TestFiles.ensure_dir(name)
|
||||
if File.exists?(name)
|
||||
return if File.stat(name).directory?
|
||||
File.delete(name)
|
||||
end
|
||||
Dir.mkdir(name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
# For representation and creation of
|
||||
# test data
|
||||
class TestZipFile
|
||||
attr_accessor :zip_name, :entry_names, :comment
|
||||
|
||||
def initialize(zip_name, entry_names, comment = "")
|
||||
@zip_name=zip_name
|
||||
@entry_names=entry_names
|
||||
if "".respond_to? :force_encoding
|
||||
@entry_names.each {|name| name.force_encoding("ASCII-8BIT")}
|
||||
end
|
||||
@comment = comment
|
||||
end
|
||||
|
||||
def TestZipFile.create_test_zips(recreate)
|
||||
files = Dir.entries("data/generated")
|
||||
if (recreate ||
|
||||
! (files.index(File.basename(TEST_ZIP1.zip_name)) &&
|
||||
files.index(File.basename(TEST_ZIP2.zip_name)) &&
|
||||
files.index(File.basename(TEST_ZIP3.zip_name)) &&
|
||||
files.index(File.basename(TEST_ZIP4.zip_name)) &&
|
||||
files.index("empty.txt") &&
|
||||
files.index("empty_chmod640.txt") &&
|
||||
files.index("short.txt") &&
|
||||
files.index("longAscii.txt") &&
|
||||
files.index("longBinary.bin") ))
|
||||
raise "failed to create test zip '#{TEST_ZIP1.zip_name}'" unless
|
||||
system("zip #{TEST_ZIP1.zip_name} data/file2.txt")
|
||||
raise "failed to remove entry from '#{TEST_ZIP1.zip_name}'" unless
|
||||
system("zip #{TEST_ZIP1.zip_name} -d data/file2.txt")
|
||||
|
||||
File.open("data/generated/empty.txt", "w") {}
|
||||
File.open("data/generated/empty_chmod640.txt", "w") { |f| f.chmod(0640) }
|
||||
|
||||
File.open("data/generated/short.txt", "w") { |file| file << "ABCDEF" }
|
||||
ziptestTxt=""
|
||||
File.open("data/file2.txt") { |file| ziptestTxt=file.read }
|
||||
File.open("data/generated/longAscii.txt", "w") {
|
||||
|file|
|
||||
while (file.tell < 1E5)
|
||||
file << ziptestTxt
|
||||
end
|
||||
}
|
||||
|
||||
testBinaryPattern=""
|
||||
File.open("data/generated/empty.zip") { |file| testBinaryPattern=file.read }
|
||||
testBinaryPattern *= 4
|
||||
|
||||
File.open("data/generated/longBinary.bin", "wb") {
|
||||
|file|
|
||||
while (file.tell < 3E5)
|
||||
file << testBinaryPattern << rand << "\0"
|
||||
end
|
||||
}
|
||||
raise "failed to create test zip '#{TEST_ZIP2.zip_name}'" unless
|
||||
system("zip #{TEST_ZIP2.zip_name} #{TEST_ZIP2.entry_names.join(' ')}")
|
||||
|
||||
# without bash system interprets everything after echo as parameters to
|
||||
# echo including | zip -z ...
|
||||
raise "failed to add comment to test zip '#{TEST_ZIP2.zip_name}'" unless
|
||||
system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zip_name}\"")
|
||||
|
||||
raise "failed to create test zip '#{TEST_ZIP3.zip_name}'" unless
|
||||
system("zip #{TEST_ZIP3.zip_name} #{TEST_ZIP3.entry_names.join(' ')}")
|
||||
|
||||
raise "failed to create test zip '#{TEST_ZIP4.zip_name}'" unless
|
||||
system("zip #{TEST_ZIP4.zip_name} #{TEST_ZIP4.entry_names.join(' ')}")
|
||||
end
|
||||
rescue
|
||||
raise $!.to_s +
|
||||
"\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" +
|
||||
"to create test data. If you don't have it you can download\n" +
|
||||
"the necessary test files at http://sf.net/projects/rubyzip."
|
||||
end
|
||||
|
||||
TEST_ZIP1 = TestZipFile.new("data/generated/empty.zip", [])
|
||||
TEST_ZIP2 = TestZipFile.new("data/generated/5entry.zip", %w{ data/generated/longAscii.txt data/generated/empty.txt data/generated/empty_chmod640.txt data/generated/short.txt data/generated/longBinary.bin},
|
||||
"my zip comment")
|
||||
TEST_ZIP3 = TestZipFile.new("data/generated/test1.zip", %w{ data/file1.txt })
|
||||
TEST_ZIP4 = TestZipFile.new("data/generated/zipWithDir.zip", [ "data/file1.txt",
|
||||
TestFiles::EMPTY_TEST_DIR])
|
||||
end
|
||||
|
||||
|
||||
END {
|
||||
TestFiles::create_test_files(ARGV.index("recreate") != nil ||
|
||||
ARGV.index("recreateonly") != nil)
|
||||
TestZipFile::create_test_zips(ARGV.index("recreate") != nil ||
|
||||
ARGV.index("recreateonly") != nil)
|
||||
exit if ARGV.index("recreateonly") != nil
|
||||
}
|
|
@ -1,208 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'test/unit'
|
||||
require 'zip/ioextras'
|
||||
|
||||
include IOExtras
|
||||
|
||||
class FakeIOTest < Test::Unit::TestCase
|
||||
class FakeIOUsingClass
|
||||
include FakeIO
|
||||
end
|
||||
|
||||
def test_kind_of?
|
||||
obj = FakeIOUsingClass.new
|
||||
|
||||
assert(obj.kind_of?(Object))
|
||||
assert(obj.kind_of?(FakeIOUsingClass))
|
||||
assert(obj.kind_of?(IO))
|
||||
assert(!obj.kind_of?(Fixnum))
|
||||
assert(!obj.kind_of?(String))
|
||||
end
|
||||
end
|
||||
|
||||
class AbstractInputStreamTest < Test::Unit::TestCase
|
||||
# AbstractInputStream subclass that provides a read method
|
||||
|
||||
TEST_LINES = [ "Hello world#{$/}",
|
||||
"this is the second line#{$/}",
|
||||
"this is the last line"]
|
||||
TEST_STRING = TEST_LINES.join
|
||||
class TestAbstractInputStream
|
||||
include AbstractInputStream
|
||||
def initialize(aString)
|
||||
super()
|
||||
@contents = aString
|
||||
@readPointer = 0
|
||||
end
|
||||
|
||||
def read(charsToRead)
|
||||
retVal=@contents[@readPointer, charsToRead]
|
||||
@readPointer+=charsToRead
|
||||
return retVal
|
||||
end
|
||||
|
||||
def produce_input
|
||||
read(100)
|
||||
end
|
||||
|
||||
def input_finished?
|
||||
@contents[@readPointer] == nil
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
@io = TestAbstractInputStream.new(TEST_STRING)
|
||||
end
|
||||
|
||||
def test_gets
|
||||
assert_equal(TEST_LINES[0], @io.gets)
|
||||
assert_equal(1, @io.lineno)
|
||||
assert_equal(TEST_LINES[1], @io.gets)
|
||||
assert_equal(2, @io.lineno)
|
||||
assert_equal(TEST_LINES[2], @io.gets)
|
||||
assert_equal(3, @io.lineno)
|
||||
assert_equal(nil, @io.gets)
|
||||
assert_equal(4, @io.lineno)
|
||||
end
|
||||
|
||||
def test_getsMultiCharSeperator
|
||||
assert_equal("Hell", @io.gets("ll"))
|
||||
assert_equal("o world#{$/}this is the second l", @io.gets("d l"))
|
||||
end
|
||||
|
||||
def test_each_line
|
||||
lineNumber=0
|
||||
@io.each_line {
|
||||
|line|
|
||||
assert_equal(TEST_LINES[lineNumber], line)
|
||||
lineNumber+=1
|
||||
}
|
||||
end
|
||||
|
||||
def test_readlines
|
||||
assert_equal(TEST_LINES, @io.readlines)
|
||||
end
|
||||
|
||||
def test_readline
|
||||
test_gets
|
||||
begin
|
||||
@io.readline
|
||||
fail "EOFError expected"
|
||||
rescue EOFError
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class AbstractOutputStreamTest < Test::Unit::TestCase
|
||||
class TestOutputStream
|
||||
include AbstractOutputStream
|
||||
|
||||
attr_accessor :buffer
|
||||
|
||||
def initialize
|
||||
@buffer = ""
|
||||
end
|
||||
|
||||
def << (data)
|
||||
@buffer << data
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
@outputStream = TestOutputStream.new
|
||||
|
||||
@origCommaSep = $,
|
||||
@origOutputSep = $\
|
||||
end
|
||||
|
||||
def teardown
|
||||
$, = @origCommaSep
|
||||
$\ = @origOutputSep
|
||||
end
|
||||
|
||||
def test_write
|
||||
count = @outputStream.write("a little string")
|
||||
assert_equal("a little string", @outputStream.buffer)
|
||||
assert_equal("a little string".length, count)
|
||||
|
||||
count = @outputStream.write(". a little more")
|
||||
assert_equal("a little string. a little more", @outputStream.buffer)
|
||||
assert_equal(". a little more".length, count)
|
||||
end
|
||||
|
||||
def test_print
|
||||
$\ = nil # record separator set to nil
|
||||
@outputStream.print("hello")
|
||||
assert_equal("hello", @outputStream.buffer)
|
||||
|
||||
@outputStream.print(" world.")
|
||||
assert_equal("hello world.", @outputStream.buffer)
|
||||
|
||||
@outputStream.print(" You ok ", "out ", "there?")
|
||||
assert_equal("hello world. You ok out there?", @outputStream.buffer)
|
||||
|
||||
$\ = "\n"
|
||||
@outputStream.print
|
||||
assert_equal("hello world. You ok out there?\n", @outputStream.buffer)
|
||||
|
||||
@outputStream.print("I sure hope so!")
|
||||
assert_equal("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer)
|
||||
|
||||
$, = "X"
|
||||
@outputStream.buffer = ""
|
||||
@outputStream.print("monkey", "duck", "zebra")
|
||||
assert_equal("monkeyXduckXzebra\n", @outputStream.buffer)
|
||||
|
||||
$\ = nil
|
||||
@outputStream.buffer = ""
|
||||
@outputStream.print(20)
|
||||
assert_equal("20", @outputStream.buffer)
|
||||
end
|
||||
|
||||
def test_printf
|
||||
@outputStream.printf("%d %04x", 123, 123)
|
||||
assert_equal("123 007b", @outputStream.buffer)
|
||||
end
|
||||
|
||||
def test_putc
|
||||
@outputStream.putc("A")
|
||||
assert_equal("A", @outputStream.buffer)
|
||||
@outputStream.putc(65)
|
||||
assert_equal("AA", @outputStream.buffer)
|
||||
end
|
||||
|
||||
def test_puts
|
||||
@outputStream.puts
|
||||
assert_equal("\n", @outputStream.buffer)
|
||||
|
||||
@outputStream.puts("hello", "world")
|
||||
assert_equal("\nhello\nworld\n", @outputStream.buffer)
|
||||
|
||||
@outputStream.buffer = ""
|
||||
@outputStream.puts("hello\n", "world\n")
|
||||
assert_equal("hello\nworld\n", @outputStream.buffer)
|
||||
|
||||
@outputStream.buffer = ""
|
||||
@outputStream.puts(["hello\n", "world\n"])
|
||||
assert_equal("hello\nworld\n", @outputStream.buffer)
|
||||
|
||||
@outputStream.buffer = ""
|
||||
@outputStream.puts(["hello\n", "world\n"], "bingo")
|
||||
assert_equal("hello\nworld\nbingo\n", @outputStream.buffer)
|
||||
|
||||
@outputStream.buffer = ""
|
||||
@outputStream.puts(16, 20, 50, "hello")
|
||||
assert_equal("16\n20\n50\nhello\n", @outputStream.buffer)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Copyright (C) 2002-2004 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'test/unit'
|
||||
require 'zip/stdrubyext'
|
||||
|
||||
class ModuleTest < Test::Unit::TestCase
|
||||
|
||||
def test_select_map
|
||||
assert_equal([2, 4, 8, 10], [1, 2, 3, 4, 5].select_map { |e| e == 3 ? nil : 2*e })
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class StringExtensionsTest < Test::Unit::TestCase
|
||||
|
||||
def test_starts_with
|
||||
assert("hello".starts_with(""))
|
||||
assert("hello".starts_with("h"))
|
||||
assert("hello".starts_with("he"))
|
||||
assert(! "hello".starts_with("hello there"))
|
||||
assert(! "hello".starts_with(" he"))
|
||||
|
||||
assert_raise(TypeError, "type mismatch: NilClass given") {
|
||||
"hello".starts_with(nil)
|
||||
}
|
||||
end
|
||||
|
||||
def test_ends_with
|
||||
assert("hello".ends_with("o"))
|
||||
assert("hello".ends_with("lo"))
|
||||
assert("hello".ends_with("hello"))
|
||||
assert(!"howdy".ends_with("o"))
|
||||
assert(!"howdy".ends_with("oy"))
|
||||
assert(!"howdy".ends_with("howdy doody"))
|
||||
assert(!"howdy".ends_with("doody howdy"))
|
||||
end
|
||||
|
||||
def test_ensure_end
|
||||
assert_equal("hello!", "hello!".ensure_end("!"))
|
||||
assert_equal("hello!", "hello!".ensure_end("o!"))
|
||||
assert_equal("hello!", "hello".ensure_end("!"))
|
||||
assert_equal("hello!", "hel".ensure_end("lo!"))
|
||||
end
|
||||
end
|
||||
|
||||
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,845 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'zip/zipfilesystem'
|
||||
require 'test/unit'
|
||||
require 'fileutils'
|
||||
|
||||
module ExtraAssertions
|
||||
|
||||
def assert_forwarded(anObject, method, retVal, *expectedArgs)
|
||||
callArgs = nil
|
||||
setCallArgsProc = proc { |args| callArgs = args }
|
||||
anObject.instance_eval <<-"end_eval"
|
||||
alias #{method}_org #{method}
|
||||
def #{method}(*args)
|
||||
ObjectSpace._id2ref(#{setCallArgsProc.object_id}).call(args)
|
||||
ObjectSpace._id2ref(#{retVal.object_id})
|
||||
end
|
||||
end_eval
|
||||
|
||||
assert_equal(retVal, yield) # Invoke test
|
||||
assert_equal(expectedArgs, callArgs)
|
||||
ensure
|
||||
anObject.instance_eval "undef #{method}; alias #{method} #{method}_org"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
include Zip
|
||||
|
||||
class ZipFsFileNonmutatingTest < Test::Unit::TestCase
|
||||
def setup
|
||||
@zipFile = ZipFile.new("data/zipWithDirs.zip")
|
||||
end
|
||||
|
||||
def teardown
|
||||
@zipFile.close if @zipFile
|
||||
end
|
||||
|
||||
def test_umask
|
||||
assert_equal(File.umask, @zipFile.file.umask)
|
||||
@zipFile.file.umask(0006)
|
||||
end
|
||||
|
||||
def test_exists?
|
||||
assert(! @zipFile.file.exists?("notAFile"))
|
||||
assert(@zipFile.file.exists?("file1"))
|
||||
assert(@zipFile.file.exists?("dir1"))
|
||||
assert(@zipFile.file.exists?("dir1/"))
|
||||
assert(@zipFile.file.exists?("dir1/file12"))
|
||||
assert(@zipFile.file.exist?("dir1/file12")) # notice, tests exist? alias of exists? !
|
||||
|
||||
@zipFile.dir.chdir "dir1/"
|
||||
assert(!@zipFile.file.exists?("file1"))
|
||||
assert(@zipFile.file.exists?("file12"))
|
||||
end
|
||||
|
||||
def test_open_read
|
||||
blockCalled = false
|
||||
@zipFile.file.open("file1", "r") {
|
||||
|f|
|
||||
blockCalled = true
|
||||
assert_equal("this is the entry 'file1' in my test archive!",
|
||||
f.readline.chomp)
|
||||
}
|
||||
assert(blockCalled)
|
||||
|
||||
blockCalled = false
|
||||
@zipFile.file.open("file1", "rb") { # test binary flag is ignored
|
||||
|f|
|
||||
blockCalled = true
|
||||
assert_equal("this is the entry 'file1' in my test archive!",
|
||||
f.readline.chomp)
|
||||
}
|
||||
assert(blockCalled)
|
||||
|
||||
blockCalled = false
|
||||
@zipFile.dir.chdir "dir2"
|
||||
@zipFile.file.open("file21", "r") {
|
||||
|f|
|
||||
blockCalled = true
|
||||
assert_equal("this is the entry 'dir2/file21' in my test archive!",
|
||||
f.readline.chomp)
|
||||
}
|
||||
assert(blockCalled)
|
||||
@zipFile.dir.chdir "/"
|
||||
|
||||
assert_raise(Errno::ENOENT) {
|
||||
@zipFile.file.open("noSuchEntry")
|
||||
}
|
||||
|
||||
begin
|
||||
is = @zipFile.file.open("file1")
|
||||
assert_equal("this is the entry 'file1' in my test archive!",
|
||||
is.readline.chomp)
|
||||
ensure
|
||||
is.close if is
|
||||
end
|
||||
end
|
||||
|
||||
def test_new
|
||||
begin
|
||||
is = @zipFile.file.new("file1")
|
||||
assert_equal("this is the entry 'file1' in my test archive!",
|
||||
is.readline.chomp)
|
||||
ensure
|
||||
is.close if is
|
||||
end
|
||||
begin
|
||||
is = @zipFile.file.new("file1") {
|
||||
fail "should not call block"
|
||||
}
|
||||
ensure
|
||||
is.close if is
|
||||
end
|
||||
end
|
||||
|
||||
def test_symlink
|
||||
assert_raise(NotImplementedError) {
|
||||
@zipFile.file.symlink("file1", "aSymlink")
|
||||
}
|
||||
end
|
||||
|
||||
def test_size
|
||||
assert_raise(Errno::ENOENT) { @zipFile.file.size("notAFile") }
|
||||
assert_equal(72, @zipFile.file.size("file1"))
|
||||
assert_equal(0, @zipFile.file.size("dir2/dir21"))
|
||||
|
||||
assert_equal(72, @zipFile.file.stat("file1").size)
|
||||
assert_equal(0, @zipFile.file.stat("dir2/dir21").size)
|
||||
end
|
||||
|
||||
def test_size?
|
||||
assert_equal(nil, @zipFile.file.size?("notAFile"))
|
||||
assert_equal(72, @zipFile.file.size?("file1"))
|
||||
assert_equal(nil, @zipFile.file.size?("dir2/dir21"))
|
||||
|
||||
assert_equal(72, @zipFile.file.stat("file1").size?)
|
||||
assert_equal(nil, @zipFile.file.stat("dir2/dir21").size?)
|
||||
end
|
||||
|
||||
|
||||
def test_file?
|
||||
assert(@zipFile.file.file?("file1"))
|
||||
assert(@zipFile.file.file?("dir2/file21"))
|
||||
assert(! @zipFile.file.file?("dir1"))
|
||||
assert(! @zipFile.file.file?("dir1/dir11"))
|
||||
|
||||
assert(@zipFile.file.stat("file1").file?)
|
||||
assert(@zipFile.file.stat("dir2/file21").file?)
|
||||
assert(! @zipFile.file.stat("dir1").file?)
|
||||
assert(! @zipFile.file.stat("dir1/dir11").file?)
|
||||
end
|
||||
|
||||
include ExtraAssertions
|
||||
|
||||
def test_dirname
|
||||
assert_forwarded(File, :dirname, "retVal", "a/b/c/d") {
|
||||
@zipFile.file.dirname("a/b/c/d")
|
||||
}
|
||||
end
|
||||
|
||||
def test_basename
|
||||
assert_forwarded(File, :basename, "retVal", "a/b/c/d") {
|
||||
@zipFile.file.basename("a/b/c/d")
|
||||
}
|
||||
end
|
||||
|
||||
def test_split
|
||||
assert_forwarded(File, :split, "retVal", "a/b/c/d") {
|
||||
@zipFile.file.split("a/b/c/d")
|
||||
}
|
||||
end
|
||||
|
||||
def test_join
|
||||
assert_equal("a/b/c", @zipFile.file.join("a/b", "c"))
|
||||
assert_equal("a/b/c/d", @zipFile.file.join("a/b", "c/d"))
|
||||
assert_equal("/c/d", @zipFile.file.join("", "c/d"))
|
||||
assert_equal("a/b/c/d", @zipFile.file.join("a", "b", "c", "d"))
|
||||
end
|
||||
|
||||
def test_utime
|
||||
t_now = Time.now
|
||||
t_bak = @zipFile.file.mtime("file1")
|
||||
@zipFile.file.utime(t_now, "file1")
|
||||
assert_equal(t_now, @zipFile.file.mtime("file1"))
|
||||
@zipFile.file.utime(t_bak, "file1")
|
||||
assert_equal(t_bak, @zipFile.file.mtime("file1"))
|
||||
end
|
||||
|
||||
|
||||
def assert_always_false(operation)
|
||||
assert(! @zipFile.file.send(operation, "noSuchFile"))
|
||||
assert(! @zipFile.file.send(operation, "file1"))
|
||||
assert(! @zipFile.file.send(operation, "dir1"))
|
||||
assert(! @zipFile.file.stat("file1").send(operation))
|
||||
assert(! @zipFile.file.stat("dir1").send(operation))
|
||||
end
|
||||
|
||||
def assert_true_if_entry_exists(operation)
|
||||
assert(! @zipFile.file.send(operation, "noSuchFile"))
|
||||
assert(@zipFile.file.send(operation, "file1"))
|
||||
assert(@zipFile.file.send(operation, "dir1"))
|
||||
assert(@zipFile.file.stat("file1").send(operation))
|
||||
assert(@zipFile.file.stat("dir1").send(operation))
|
||||
end
|
||||
|
||||
def test_pipe?
|
||||
assert_always_false(:pipe?)
|
||||
end
|
||||
|
||||
def test_blockdev?
|
||||
assert_always_false(:blockdev?)
|
||||
end
|
||||
|
||||
def test_symlink?
|
||||
assert_always_false(:symlink?)
|
||||
end
|
||||
|
||||
def test_socket?
|
||||
assert_always_false(:socket?)
|
||||
end
|
||||
|
||||
def test_chardev?
|
||||
assert_always_false(:chardev?)
|
||||
end
|
||||
|
||||
def test_truncate
|
||||
assert_raise(StandardError, "truncate not supported") {
|
||||
@zipFile.file.truncate("file1", 100)
|
||||
}
|
||||
end
|
||||
|
||||
def assert_e_n_o_e_n_t(operation, args = ["NoSuchFile"])
|
||||
assert_raise(Errno::ENOENT) {
|
||||
@zipFile.file.send(operation, *args)
|
||||
}
|
||||
end
|
||||
|
||||
def test_ftype
|
||||
assert_e_n_o_e_n_t(:ftype)
|
||||
assert_equal("file", @zipFile.file.ftype("file1"))
|
||||
assert_equal("directory", @zipFile.file.ftype("dir1/dir11"))
|
||||
assert_equal("directory", @zipFile.file.ftype("dir1/dir11/"))
|
||||
end
|
||||
|
||||
def test_link
|
||||
assert_raise(NotImplementedError) {
|
||||
@zipFile.file.link("file1", "someOtherString")
|
||||
}
|
||||
end
|
||||
|
||||
def test_directory?
|
||||
assert(! @zipFile.file.directory?("notAFile"))
|
||||
assert(! @zipFile.file.directory?("file1"))
|
||||
assert(! @zipFile.file.directory?("dir1/file11"))
|
||||
assert(@zipFile.file.directory?("dir1"))
|
||||
assert(@zipFile.file.directory?("dir1/"))
|
||||
assert(@zipFile.file.directory?("dir2/dir21"))
|
||||
|
||||
assert(! @zipFile.file.stat("file1").directory?)
|
||||
assert(! @zipFile.file.stat("dir1/file11").directory?)
|
||||
assert(@zipFile.file.stat("dir1").directory?)
|
||||
assert(@zipFile.file.stat("dir1/").directory?)
|
||||
assert(@zipFile.file.stat("dir2/dir21").directory?)
|
||||
end
|
||||
|
||||
def test_chown
|
||||
assert_equal(2, @zipFile.file.chown(1,2, "dir1", "file1"))
|
||||
assert_equal(1, @zipFile.file.stat("dir1").uid)
|
||||
assert_equal(2, @zipFile.file.stat("dir1").gid)
|
||||
assert_equal(2, @zipFile.file.chown(nil, nil, "dir1", "file1"))
|
||||
end
|
||||
|
||||
def test_zero?
|
||||
assert(! @zipFile.file.zero?("notAFile"))
|
||||
assert(! @zipFile.file.zero?("file1"))
|
||||
assert(@zipFile.file.zero?("dir1"))
|
||||
blockCalled = false
|
||||
ZipFile.open("data/generated/5entry.zip") {
|
||||
|zf|
|
||||
blockCalled = true
|
||||
assert(zf.file.zero?("data/generated/empty.txt"))
|
||||
}
|
||||
assert(blockCalled)
|
||||
|
||||
assert(! @zipFile.file.stat("file1").zero?)
|
||||
assert(@zipFile.file.stat("dir1").zero?)
|
||||
blockCalled = false
|
||||
ZipFile.open("data/generated/5entry.zip") {
|
||||
|zf|
|
||||
blockCalled = true
|
||||
assert(zf.file.stat("data/generated/empty.txt").zero?)
|
||||
}
|
||||
assert(blockCalled)
|
||||
end
|
||||
|
||||
def test_expand_path
|
||||
ZipFile.open("data/zipWithDirs.zip") {
|
||||
|zf|
|
||||
assert_equal("/", zf.file.expand_path("."))
|
||||
zf.dir.chdir "dir1"
|
||||
assert_equal("/dir1", zf.file.expand_path("."))
|
||||
assert_equal("/dir1/file12", zf.file.expand_path("file12"))
|
||||
assert_equal("/", zf.file.expand_path(".."))
|
||||
assert_equal("/dir2/dir21", zf.file.expand_path("../dir2/dir21"))
|
||||
}
|
||||
end
|
||||
|
||||
def test_mtime
|
||||
assert_equal(Time.at(1027694306),
|
||||
@zipFile.file.mtime("dir2/file21"))
|
||||
assert_equal(Time.at(1027690863),
|
||||
@zipFile.file.mtime("dir2/dir21"))
|
||||
assert_raise(Errno::ENOENT) {
|
||||
@zipFile.file.mtime("noSuchEntry")
|
||||
}
|
||||
|
||||
assert_equal(Time.at(1027694306),
|
||||
@zipFile.file.stat("dir2/file21").mtime)
|
||||
assert_equal(Time.at(1027690863),
|
||||
@zipFile.file.stat("dir2/dir21").mtime)
|
||||
end
|
||||
|
||||
def test_ctime
|
||||
assert_nil(@zipFile.file.ctime("file1"))
|
||||
assert_nil(@zipFile.file.stat("file1").ctime)
|
||||
end
|
||||
|
||||
def test_atime
|
||||
assert_nil(@zipFile.file.atime("file1"))
|
||||
assert_nil(@zipFile.file.stat("file1").atime)
|
||||
end
|
||||
|
||||
def test_readable?
|
||||
assert(! @zipFile.file.readable?("noSuchFile"))
|
||||
assert(@zipFile.file.readable?("file1"))
|
||||
assert(@zipFile.file.readable?("dir1"))
|
||||
assert(@zipFile.file.stat("file1").readable?)
|
||||
assert(@zipFile.file.stat("dir1").readable?)
|
||||
end
|
||||
|
||||
def test_readable_real?
|
||||
assert(! @zipFile.file.readable_real?("noSuchFile"))
|
||||
assert(@zipFile.file.readable_real?("file1"))
|
||||
assert(@zipFile.file.readable_real?("dir1"))
|
||||
assert(@zipFile.file.stat("file1").readable_real?)
|
||||
assert(@zipFile.file.stat("dir1").readable_real?)
|
||||
end
|
||||
|
||||
def test_writable?
|
||||
assert(! @zipFile.file.writable?("noSuchFile"))
|
||||
assert(@zipFile.file.writable?("file1"))
|
||||
assert(@zipFile.file.writable?("dir1"))
|
||||
assert(@zipFile.file.stat("file1").writable?)
|
||||
assert(@zipFile.file.stat("dir1").writable?)
|
||||
end
|
||||
|
||||
def test_writable_real?
|
||||
assert(! @zipFile.file.writable_real?("noSuchFile"))
|
||||
assert(@zipFile.file.writable_real?("file1"))
|
||||
assert(@zipFile.file.writable_real?("dir1"))
|
||||
assert(@zipFile.file.stat("file1").writable_real?)
|
||||
assert(@zipFile.file.stat("dir1").writable_real?)
|
||||
end
|
||||
|
||||
def test_executable?
|
||||
assert(! @zipFile.file.executable?("noSuchFile"))
|
||||
assert(! @zipFile.file.executable?("file1"))
|
||||
assert(@zipFile.file.executable?("dir1"))
|
||||
assert(! @zipFile.file.stat("file1").executable?)
|
||||
assert(@zipFile.file.stat("dir1").executable?)
|
||||
end
|
||||
|
||||
def test_executable_real?
|
||||
assert(! @zipFile.file.executable_real?("noSuchFile"))
|
||||
assert(! @zipFile.file.executable_real?("file1"))
|
||||
assert(@zipFile.file.executable_real?("dir1"))
|
||||
assert(! @zipFile.file.stat("file1").executable_real?)
|
||||
assert(@zipFile.file.stat("dir1").executable_real?)
|
||||
end
|
||||
|
||||
def test_owned?
|
||||
assert_true_if_entry_exists(:owned?)
|
||||
end
|
||||
|
||||
def test_grpowned?
|
||||
assert_true_if_entry_exists(:grpowned?)
|
||||
end
|
||||
|
||||
def test_setgid?
|
||||
assert_always_false(:setgid?)
|
||||
end
|
||||
|
||||
def test_setuid?
|
||||
assert_always_false(:setgid?)
|
||||
end
|
||||
|
||||
def test_sticky?
|
||||
assert_always_false(:sticky?)
|
||||
end
|
||||
|
||||
def test_readlink
|
||||
assert_raise(NotImplementedError) {
|
||||
@zipFile.file.readlink("someString")
|
||||
}
|
||||
end
|
||||
|
||||
def test_stat
|
||||
s = @zipFile.file.stat("file1")
|
||||
assert(s.kind_of?(File::Stat)) # It pretends
|
||||
assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") {
|
||||
@zipFile.file.stat("noSuchFile")
|
||||
}
|
||||
end
|
||||
|
||||
def test_lstat
|
||||
assert(@zipFile.file.lstat("file1").file?)
|
||||
end
|
||||
|
||||
|
||||
def test_chmod
|
||||
assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") {
|
||||
@zipFile.file.chmod(0644, "file1", "NoSuchFile")
|
||||
}
|
||||
assert_equal(2, @zipFile.file.chmod(0644, "file1", "dir1"))
|
||||
end
|
||||
|
||||
def test_pipe
|
||||
assert_raise(NotImplementedError) {
|
||||
@zipFile.file.pipe
|
||||
}
|
||||
end
|
||||
|
||||
def test_foreach
|
||||
ZipFile.open("data/generated/zipWithDir.zip") {
|
||||
|zf|
|
||||
ref = []
|
||||
File.foreach("data/file1.txt") { |e| ref << e }
|
||||
|
||||
index = 0
|
||||
zf.file.foreach("data/file1.txt") {
|
||||
|l|
|
||||
assert_equal(ref[index], l)
|
||||
index = index.next
|
||||
}
|
||||
assert_equal(ref.size, index)
|
||||
}
|
||||
|
||||
ZipFile.open("data/generated/zipWithDir.zip") {
|
||||
|zf|
|
||||
ref = []
|
||||
File.foreach("data/file1.txt", " ") { |e| ref << e }
|
||||
|
||||
index = 0
|
||||
zf.file.foreach("data/file1.txt", " ") {
|
||||
|l|
|
||||
assert_equal(ref[index], l)
|
||||
index = index.next
|
||||
}
|
||||
assert_equal(ref.size, index)
|
||||
}
|
||||
end
|
||||
|
||||
def test_popen
|
||||
if RUBY_PLATFORM =~ /mswin|mingw/i
|
||||
cmd = 'dir'
|
||||
else
|
||||
cmd = 'ls'
|
||||
end
|
||||
|
||||
assert_equal(File.popen(cmd) { |f| f.read },
|
||||
@zipFile.file.popen(cmd) { |f| f.read })
|
||||
end
|
||||
|
||||
# Can be added later
|
||||
# def test_select
|
||||
# fail "implement test"
|
||||
# end
|
||||
|
||||
def test_readlines
|
||||
ZipFile.open("data/generated/zipWithDir.zip") {
|
||||
|zf|
|
||||
assert_equal(File.readlines("data/file1.txt"),
|
||||
zf.file.readlines("data/file1.txt"))
|
||||
}
|
||||
end
|
||||
|
||||
def test_read
|
||||
ZipFile.open("data/generated/zipWithDir.zip") {
|
||||
|zf|
|
||||
assert_equal(File.read("data/file1.txt"),
|
||||
zf.file.read("data/file1.txt"))
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ZipFsFileStatTest < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
@zipFile = ZipFile.new("data/zipWithDirs.zip")
|
||||
end
|
||||
|
||||
def teardown
|
||||
@zipFile.close if @zipFile
|
||||
end
|
||||
|
||||
def test_blocks
|
||||
assert_equal(nil, @zipFile.file.stat("file1").blocks)
|
||||
end
|
||||
|
||||
def test_ino
|
||||
assert_equal(0, @zipFile.file.stat("file1").ino)
|
||||
end
|
||||
|
||||
def test_uid
|
||||
assert_equal(0, @zipFile.file.stat("file1").uid)
|
||||
end
|
||||
|
||||
def test_gid
|
||||
assert_equal(0, @zipFile.file.stat("file1").gid)
|
||||
end
|
||||
|
||||
def test_ftype
|
||||
assert_equal("file", @zipFile.file.stat("file1").ftype)
|
||||
assert_equal("directory", @zipFile.file.stat("dir1").ftype)
|
||||
end
|
||||
|
||||
def test_mode
|
||||
assert_equal(0600, @zipFile.file.stat("file1").mode & 0777)
|
||||
assert_equal(0600, @zipFile.file.stat("file1").mode & 0777)
|
||||
assert_equal(0755, @zipFile.file.stat("dir1").mode & 0777)
|
||||
assert_equal(0755, @zipFile.file.stat("dir1").mode & 0777)
|
||||
end
|
||||
|
||||
def test_dev
|
||||
assert_equal(0, @zipFile.file.stat("file1").dev)
|
||||
end
|
||||
|
||||
def test_rdev
|
||||
assert_equal(0, @zipFile.file.stat("file1").rdev)
|
||||
end
|
||||
|
||||
def test_rdev_major
|
||||
assert_equal(0, @zipFile.file.stat("file1").rdev_major)
|
||||
end
|
||||
|
||||
def test_rdev_minor
|
||||
assert_equal(0, @zipFile.file.stat("file1").rdev_minor)
|
||||
end
|
||||
|
||||
def test_nlink
|
||||
assert_equal(1, @zipFile.file.stat("file1").nlink)
|
||||
end
|
||||
|
||||
def test_blksize
|
||||
assert_nil(@zipFile.file.stat("file1").blksize)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ZipFsFileMutatingTest < Test::Unit::TestCase
|
||||
TEST_ZIP = "zipWithDirs_copy.zip"
|
||||
def setup
|
||||
FileUtils.cp("data/zipWithDirs.zip", TEST_ZIP)
|
||||
end
|
||||
|
||||
def teardown
|
||||
end
|
||||
|
||||
def test_delete
|
||||
do_test_delete_or_unlink(:delete)
|
||||
end
|
||||
|
||||
def test_unlink
|
||||
do_test_delete_or_unlink(:unlink)
|
||||
end
|
||||
|
||||
def test_open_write
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
|
||||
zf.file.open("test_open_write_entry", "w") {
|
||||
|f|
|
||||
blockCalled = true
|
||||
f.write "This is what I'm writing"
|
||||
}
|
||||
assert_equal("This is what I'm writing",
|
||||
zf.file.read("test_open_write_entry"))
|
||||
|
||||
# Test with existing entry
|
||||
zf.file.open("file1", "wb") { #also check that 'b' option is ignored
|
||||
|f|
|
||||
blockCalled = true
|
||||
f.write "This is what I'm writing too"
|
||||
}
|
||||
assert_equal("This is what I'm writing too",
|
||||
zf.file.read("file1"))
|
||||
}
|
||||
end
|
||||
|
||||
def test_rename
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert_raise(Errno::ENOENT, "") {
|
||||
zf.file.rename("NoSuchFile", "bimse")
|
||||
}
|
||||
zf.file.rename("file1", "newNameForFile1")
|
||||
}
|
||||
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert(! zf.file.exists?("file1"))
|
||||
assert(zf.file.exists?("newNameForFile1"))
|
||||
}
|
||||
end
|
||||
|
||||
def do_test_delete_or_unlink(symbol)
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert(zf.file.exists?("dir2/dir21/dir221/file2221"))
|
||||
zf.file.send(symbol, "dir2/dir21/dir221/file2221")
|
||||
assert(! zf.file.exists?("dir2/dir21/dir221/file2221"))
|
||||
|
||||
assert(zf.file.exists?("dir1/file11"))
|
||||
assert(zf.file.exists?("dir1/file12"))
|
||||
zf.file.send(symbol, "dir1/file11", "dir1/file12")
|
||||
assert(! zf.file.exists?("dir1/file11"))
|
||||
assert(! zf.file.exists?("dir1/file12"))
|
||||
|
||||
assert_raise(Errno::ENOENT) { zf.file.send(symbol, "noSuchFile") }
|
||||
assert_raise(Errno::EISDIR) { zf.file.send(symbol, "dir1/dir11") }
|
||||
assert_raise(Errno::EISDIR) { zf.file.send(symbol, "dir1/dir11/") }
|
||||
}
|
||||
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert(! zf.file.exists?("dir2/dir21/dir221/file2221"))
|
||||
assert(! zf.file.exists?("dir1/file11"))
|
||||
assert(! zf.file.exists?("dir1/file12"))
|
||||
|
||||
assert(zf.file.exists?("dir1/dir11"))
|
||||
assert(zf.file.exists?("dir1/dir11/"))
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ZipFsDirectoryTest < Test::Unit::TestCase
|
||||
TEST_ZIP = "zipWithDirs_copy.zip"
|
||||
|
||||
def setup
|
||||
FileUtils.cp("data/zipWithDirs.zip", TEST_ZIP)
|
||||
end
|
||||
|
||||
def test_delete
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert_raise(Errno::ENOENT, "No such file or directory - NoSuchFile.txt") {
|
||||
zf.dir.delete("NoSuchFile.txt")
|
||||
}
|
||||
assert_raise(Errno::EINVAL, "Invalid argument - file1") {
|
||||
zf.dir.delete("file1")
|
||||
}
|
||||
assert(zf.file.exists?("dir1"))
|
||||
zf.dir.delete("dir1")
|
||||
assert(! zf.file.exists?("dir1"))
|
||||
}
|
||||
end
|
||||
|
||||
def test_mkdir
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert_raise(Errno::EEXIST, "File exists - dir1") {
|
||||
zf.dir.mkdir("file1")
|
||||
}
|
||||
assert_raise(Errno::EEXIST, "File exists - dir1") {
|
||||
zf.dir.mkdir("dir1")
|
||||
}
|
||||
assert(!zf.file.exists?("newDir"))
|
||||
zf.dir.mkdir("newDir")
|
||||
assert(zf.file.directory?("newDir"))
|
||||
assert(!zf.file.exists?("newDir2"))
|
||||
zf.dir.mkdir("newDir2", 3485)
|
||||
assert(zf.file.directory?("newDir2"))
|
||||
}
|
||||
end
|
||||
|
||||
def test_pwd_chdir_entries
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert_equal("/", zf.dir.pwd)
|
||||
|
||||
assert_raise(Errno::ENOENT, "No such file or directory - no such dir") {
|
||||
zf.dir.chdir "no such dir"
|
||||
}
|
||||
|
||||
assert_raise(Errno::EINVAL, "Invalid argument - file1") {
|
||||
zf.dir.chdir "file1"
|
||||
}
|
||||
|
||||
assert_equal(["dir1", "dir2", "file1"].sort, zf.dir.entries(".").sort)
|
||||
zf.dir.chdir "dir1"
|
||||
assert_equal("/dir1", zf.dir.pwd)
|
||||
assert_equal(["dir11", "file11", "file12"], zf.dir.entries(".").sort)
|
||||
|
||||
zf.dir.chdir "../dir2/dir21"
|
||||
assert_equal("/dir2/dir21", zf.dir.pwd)
|
||||
assert_equal(["dir221"].sort, zf.dir.entries(".").sort)
|
||||
}
|
||||
end
|
||||
|
||||
def test_foreach
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
|
||||
blockCalled = false
|
||||
assert_raise(Errno::ENOENT, "No such file or directory - noSuchDir") {
|
||||
zf.dir.foreach("noSuchDir") { |e| blockCalled = true }
|
||||
}
|
||||
assert(! blockCalled)
|
||||
|
||||
assert_raise(Errno::ENOTDIR, "Not a directory - file1") {
|
||||
zf.dir.foreach("file1") { |e| blockCalled = true }
|
||||
}
|
||||
assert(! blockCalled)
|
||||
|
||||
entries = []
|
||||
zf.dir.foreach(".") { |e| entries << e }
|
||||
assert_equal(["dir1", "dir2", "file1"].sort, entries.sort)
|
||||
|
||||
entries = []
|
||||
zf.dir.foreach("dir1") { |e| entries << e }
|
||||
assert_equal(["dir11", "file11", "file12"], entries.sort)
|
||||
}
|
||||
end
|
||||
|
||||
def test_chroot
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
assert_raise(NotImplementedError) {
|
||||
zf.dir.chroot
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
# Globbing not supported yet
|
||||
#def test_glob
|
||||
# # test alias []-operator too
|
||||
# fail "implement test"
|
||||
#end
|
||||
|
||||
def test_open_new
|
||||
ZipFile.open(TEST_ZIP) {
|
||||
|zf|
|
||||
|
||||
assert_raise(Errno::ENOTDIR, "Not a directory - file1") {
|
||||
zf.dir.new("file1")
|
||||
}
|
||||
|
||||
assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") {
|
||||
zf.dir.new("noSuchFile")
|
||||
}
|
||||
|
||||
d = zf.dir.new(".")
|
||||
assert_equal(["file1", "dir1", "dir2"].sort, d.entries.sort)
|
||||
d.close
|
||||
|
||||
zf.dir.open("dir1") {
|
||||
|dir|
|
||||
assert_equal(["dir11", "file11", "file12"].sort, dir.entries.sort)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ZipFsDirIteratorTest < Test::Unit::TestCase
|
||||
|
||||
FILENAME_ARRAY = [ "f1", "f2", "f3", "f4", "f5", "f6" ]
|
||||
|
||||
def setup
|
||||
@dirIt = ZipFileSystem::ZipFsDirIterator.new(FILENAME_ARRAY)
|
||||
end
|
||||
|
||||
def test_close
|
||||
@dirIt.close
|
||||
assert_raise(IOError, "closed directory") {
|
||||
@dirIt.each { |e| p e }
|
||||
}
|
||||
assert_raise(IOError, "closed directory") {
|
||||
@dirIt.read
|
||||
}
|
||||
assert_raise(IOError, "closed directory") {
|
||||
@dirIt.rewind
|
||||
}
|
||||
assert_raise(IOError, "closed directory") {
|
||||
@dirIt.seek(0)
|
||||
}
|
||||
assert_raise(IOError, "closed directory") {
|
||||
@dirIt.tell
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def test_each
|
||||
# Tested through Enumerable.entries
|
||||
assert_equal(FILENAME_ARRAY, @dirIt.entries)
|
||||
end
|
||||
|
||||
def test_read
|
||||
FILENAME_ARRAY.size.times {
|
||||
|i|
|
||||
assert_equal(FILENAME_ARRAY[i], @dirIt.read)
|
||||
}
|
||||
end
|
||||
|
||||
def test_rewind
|
||||
@dirIt.read
|
||||
@dirIt.read
|
||||
assert_equal(FILENAME_ARRAY[2], @dirIt.read)
|
||||
@dirIt.rewind
|
||||
assert_equal(FILENAME_ARRAY[0], @dirIt.read)
|
||||
end
|
||||
|
||||
def test_tell_seek
|
||||
@dirIt.read
|
||||
@dirIt.read
|
||||
pos = @dirIt.tell
|
||||
valAtPos = @dirIt.read
|
||||
@dirIt.read
|
||||
@dirIt.seek(pos)
|
||||
assert_equal(valAtPos, @dirIt.read)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$VERBOSE = true
|
||||
|
||||
$: << "../lib"
|
||||
|
||||
require 'test/unit'
|
||||
require 'zip/ziprequire'
|
||||
|
||||
$: << 'data/rubycode.zip' << 'data/rubycode2.zip'
|
||||
|
||||
class ZipRequireTest < Test::Unit::TestCase
|
||||
def test_require
|
||||
assert(require('data/notzippedruby'))
|
||||
assert(!require('data/notzippedruby'))
|
||||
|
||||
assert(require('zippedruby1'))
|
||||
assert(!require('zippedruby1'))
|
||||
|
||||
assert(require('zippedruby2'))
|
||||
assert(!require('zippedruby2'))
|
||||
|
||||
assert(require('zippedruby3'))
|
||||
assert(!require('zippedruby3'))
|
||||
|
||||
c1 = NotZippedRuby.new
|
||||
assert(c1.returnTrue)
|
||||
assert(ZippedRuby1.returnTrue)
|
||||
assert(!ZippedRuby2.returnFalse)
|
||||
assert_equal(4, ZippedRuby3.multiplyValues(2, 2))
|
||||
end
|
||||
|
||||
def test_get_resource
|
||||
get_resource("aResource.txt") {
|
||||
|f|
|
||||
assert_equal("Nothing exciting in this file!", f.read)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Copyright (C) 2002 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
File diff suppressed because it is too large
Load Diff
1900
lib/zip/zip.rb
1900
lib/zip/zip.rb
File diff suppressed because it is too large
Load Diff
|
@ -1,611 +0,0 @@
|
|||
# encoding: ASCII-8BIT
|
||||
require 'zip/zip'
|
||||
|
||||
module Zip
|
||||
|
||||
# The ZipFileSystem API provides an API for accessing entries in
|
||||
# a zip archive that is similar to ruby's builtin File and Dir
|
||||
# classes.
|
||||
#
|
||||
# Requiring 'zip/zipfilesystem' includes this module in ZipFile
|
||||
# making the methods in this module available on ZipFile objects.
|
||||
#
|
||||
# Using this API the following example creates a new zip file
|
||||
# <code>my.zip</code> containing a normal entry with the name
|
||||
# <code>first.txt</code>, a directory entry named <code>mydir</code>
|
||||
# and finally another normal entry named <code>second.txt</code>
|
||||
#
|
||||
# require 'zip/zipfilesystem'
|
||||
#
|
||||
# Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) {
|
||||
# |zipfile|
|
||||
# zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" }
|
||||
# zipfile.dir.mkdir("mydir")
|
||||
# zipfile.file.open("mydir/second.txt", "w") { |f| f.puts "Hello again" }
|
||||
# }
|
||||
#
|
||||
# Reading is as easy as writing, as the following example shows. The
|
||||
# example writes the contents of <code>first.txt</code> from zip archive
|
||||
# <code>my.zip</code> to standard out.
|
||||
#
|
||||
# require 'zip/zipfilesystem'
|
||||
#
|
||||
# Zip::ZipFile.open("my.zip") {
|
||||
# |zipfile|
|
||||
# puts zipfile.file.read("first.txt")
|
||||
# }
|
||||
|
||||
module ZipFileSystem
|
||||
|
||||
def initialize # :nodoc:
|
||||
mappedZip = ZipFileNameMapper.new(self)
|
||||
@zipFsDir = ZipFsDir.new(mappedZip)
|
||||
@zipFsFile = ZipFsFile.new(mappedZip)
|
||||
@zipFsDir.file = @zipFsFile
|
||||
@zipFsFile.dir = @zipFsDir
|
||||
end
|
||||
|
||||
# Returns a ZipFsDir which is much like ruby's builtin Dir (class)
|
||||
# object, except it works on the ZipFile on which this method is
|
||||
# invoked
|
||||
def dir
|
||||
@zipFsDir
|
||||
end
|
||||
|
||||
# Returns a ZipFsFile which is much like ruby's builtin File (class)
|
||||
# object, except it works on the ZipFile on which this method is
|
||||
# invoked
|
||||
def file
|
||||
@zipFsFile
|
||||
end
|
||||
|
||||
# Instances of this class are normally accessed via the accessor
|
||||
# ZipFile::file. An instance of ZipFsFile behaves like ruby's
|
||||
# builtin File (class) object, except it works on ZipFile entries.
|
||||
#
|
||||
# The individual methods are not documented due to their
|
||||
# similarity with the methods in File
|
||||
class ZipFsFile
|
||||
|
||||
attr_writer :dir
|
||||
# protected :dir
|
||||
|
||||
class ZipFsStat
|
||||
def initialize(zipFsFile, entryName)
|
||||
@zipFsFile = zipFsFile
|
||||
@entryName = entryName
|
||||
end
|
||||
|
||||
def forward_invoke(msg)
|
||||
@zipFsFile.send(msg, @entryName)
|
||||
end
|
||||
|
||||
def kind_of?(t)
|
||||
super || t == ::File::Stat
|
||||
end
|
||||
|
||||
forward_message :forward_invoke, :file?, :directory?, :pipe?, :chardev?
|
||||
forward_message :forward_invoke, :symlink?, :socket?, :blockdev?
|
||||
forward_message :forward_invoke, :readable?, :readable_real?
|
||||
forward_message :forward_invoke, :writable?, :writable_real?
|
||||
forward_message :forward_invoke, :executable?, :executable_real?
|
||||
forward_message :forward_invoke, :sticky?, :owned?, :grpowned?
|
||||
forward_message :forward_invoke, :setuid?, :setgid?
|
||||
forward_message :forward_invoke, :zero?
|
||||
forward_message :forward_invoke, :size, :size?
|
||||
forward_message :forward_invoke, :mtime, :atime, :ctime
|
||||
|
||||
def blocks; nil; end
|
||||
|
||||
def get_entry
|
||||
@zipFsFile.__send__(:get_entry, @entryName)
|
||||
end
|
||||
private :get_entry
|
||||
|
||||
def gid
|
||||
e = get_entry
|
||||
if e.extra.member? "IUnix"
|
||||
e.extra["IUnix"].gid || 0
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def uid
|
||||
e = get_entry
|
||||
if e.extra.member? "IUnix"
|
||||
e.extra["IUnix"].uid || 0
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def ino; 0; end
|
||||
|
||||
def dev; 0; end
|
||||
|
||||
def rdev; 0; end
|
||||
|
||||
def rdev_major; 0; end
|
||||
|
||||
def rdev_minor; 0; end
|
||||
|
||||
def ftype
|
||||
if file?
|
||||
return "file"
|
||||
elsif directory?
|
||||
return "directory"
|
||||
else
|
||||
raise StandardError, "Unknown file type"
|
||||
end
|
||||
end
|
||||
|
||||
def nlink; 1; end
|
||||
|
||||
def blksize; nil; end
|
||||
|
||||
def mode
|
||||
e = get_entry
|
||||
if e.fstype == 3
|
||||
e.externalFileAttributes >> 16
|
||||
else
|
||||
33206 # 33206 is equivalent to -rw-rw-rw-
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(mappedZip)
|
||||
@mappedZip = mappedZip
|
||||
end
|
||||
|
||||
def get_entry(fileName)
|
||||
if ! exists?(fileName)
|
||||
raise Errno::ENOENT, "No such file or directory - #{fileName}"
|
||||
end
|
||||
@mappedZip.find_entry(fileName)
|
||||
end
|
||||
private :get_entry
|
||||
|
||||
def unix_mode_cmp(fileName, mode)
|
||||
begin
|
||||
e = get_entry(fileName)
|
||||
e.fstype == 3 && ((e.externalFileAttributes >> 16) & mode ) != 0
|
||||
rescue Errno::ENOENT
|
||||
false
|
||||
end
|
||||
end
|
||||
private :unix_mode_cmp
|
||||
|
||||
def exists?(fileName)
|
||||
expand_path(fileName) == "/" || @mappedZip.find_entry(fileName) != nil
|
||||
end
|
||||
alias :exist? :exists?
|
||||
|
||||
# Permissions not implemented, so if the file exists it is accessible
|
||||
alias owned? exists?
|
||||
alias grpowned? exists?
|
||||
|
||||
def readable?(fileName)
|
||||
unix_mode_cmp(fileName, 0444)
|
||||
end
|
||||
alias readable_real? readable?
|
||||
|
||||
def writable?(fileName)
|
||||
unix_mode_cmp(fileName, 0222)
|
||||
end
|
||||
alias writable_real? writable?
|
||||
|
||||
def executable?(fileName)
|
||||
unix_mode_cmp(fileName, 0111)
|
||||
end
|
||||
alias executable_real? executable?
|
||||
|
||||
def setuid?(fileName)
|
||||
unix_mode_cmp(fileName, 04000)
|
||||
end
|
||||
|
||||
def setgid?(fileName)
|
||||
unix_mode_cmp(fileName, 02000)
|
||||
end
|
||||
|
||||
def sticky?(fileName)
|
||||
unix_mode_cmp(fileName, 01000)
|
||||
end
|
||||
|
||||
def umask(*args)
|
||||
::File.umask(*args)
|
||||
end
|
||||
|
||||
def truncate(fileName, len)
|
||||
raise StandardError, "truncate not supported"
|
||||
end
|
||||
|
||||
def directory?(fileName)
|
||||
entry = @mappedZip.find_entry(fileName)
|
||||
expand_path(fileName) == "/" || (entry != nil && entry.directory?)
|
||||
end
|
||||
|
||||
def open(fileName, openMode = "r", &block)
|
||||
openMode.gsub!("b", "") # ignore b option
|
||||
case openMode
|
||||
when "r"
|
||||
@mappedZip.get_input_stream(fileName, &block)
|
||||
when "w"
|
||||
@mappedZip.get_output_stream(fileName, &block)
|
||||
else
|
||||
raise StandardError, "openmode '#{openMode} not supported" unless openMode == "r"
|
||||
end
|
||||
end
|
||||
|
||||
def new(fileName, openMode = "r")
|
||||
open(fileName, openMode)
|
||||
end
|
||||
|
||||
def size(fileName)
|
||||
@mappedZip.get_entry(fileName).size
|
||||
end
|
||||
|
||||
# Returns nil for not found and nil for directories
|
||||
def size?(fileName)
|
||||
entry = @mappedZip.find_entry(fileName)
|
||||
return (entry == nil || entry.directory?) ? nil : entry.size
|
||||
end
|
||||
|
||||
def chown(ownerInt, groupInt, *filenames)
|
||||
filenames.each { |fileName|
|
||||
e = get_entry(fileName)
|
||||
unless e.extra.member?("IUnix")
|
||||
e.extra.create("IUnix")
|
||||
end
|
||||
e.extra["IUnix"].uid = ownerInt
|
||||
e.extra["IUnix"].gid = groupInt
|
||||
}
|
||||
filenames.size
|
||||
end
|
||||
|
||||
def chmod (modeInt, *filenames)
|
||||
filenames.each { |fileName|
|
||||
e = get_entry(fileName)
|
||||
e.fstype = 3 # force convertion filesystem type to unix
|
||||
e.externalFileAttributes = modeInt << 16
|
||||
}
|
||||
filenames.size
|
||||
end
|
||||
|
||||
def zero?(fileName)
|
||||
sz = size(fileName)
|
||||
sz == nil || sz == 0
|
||||
rescue Errno::ENOENT
|
||||
false
|
||||
end
|
||||
|
||||
def file?(fileName)
|
||||
entry = @mappedZip.find_entry(fileName)
|
||||
entry != nil && entry.file?
|
||||
end
|
||||
|
||||
def dirname(fileName)
|
||||
::File.dirname(fileName)
|
||||
end
|
||||
|
||||
def basename(fileName)
|
||||
::File.basename(fileName)
|
||||
end
|
||||
|
||||
def split(fileName)
|
||||
::File.split(fileName)
|
||||
end
|
||||
|
||||
def join(*fragments)
|
||||
::File.join(*fragments)
|
||||
end
|
||||
|
||||
def utime(modifiedTime, *fileNames)
|
||||
fileNames.each { |fileName|
|
||||
get_entry(fileName).time = modifiedTime
|
||||
}
|
||||
end
|
||||
|
||||
def mtime(fileName)
|
||||
@mappedZip.get_entry(fileName).mtime
|
||||
end
|
||||
|
||||
def atime(fileName)
|
||||
e = get_entry(fileName)
|
||||
if e.extra.member? "UniversalTime"
|
||||
e.extra["UniversalTime"].atime
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def ctime(fileName)
|
||||
e = get_entry(fileName)
|
||||
if e.extra.member? "UniversalTime"
|
||||
e.extra["UniversalTime"].ctime
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def pipe?(filename)
|
||||
false
|
||||
end
|
||||
|
||||
def blockdev?(filename)
|
||||
false
|
||||
end
|
||||
|
||||
def chardev?(filename)
|
||||
false
|
||||
end
|
||||
|
||||
def symlink?(fileName)
|
||||
false
|
||||
end
|
||||
|
||||
def socket?(fileName)
|
||||
false
|
||||
end
|
||||
|
||||
def ftype(fileName)
|
||||
@mappedZip.get_entry(fileName).directory? ? "directory" : "file"
|
||||
end
|
||||
|
||||
def readlink(fileName)
|
||||
raise NotImplementedError, "The readlink() function is not implemented"
|
||||
end
|
||||
|
||||
def symlink(fileName, symlinkName)
|
||||
raise NotImplementedError, "The symlink() function is not implemented"
|
||||
end
|
||||
|
||||
def link(fileName, symlinkName)
|
||||
raise NotImplementedError, "The link() function is not implemented"
|
||||
end
|
||||
|
||||
def pipe
|
||||
raise NotImplementedError, "The pipe() function is not implemented"
|
||||
end
|
||||
|
||||
def stat(fileName)
|
||||
if ! exists?(fileName)
|
||||
raise Errno::ENOENT, fileName
|
||||
end
|
||||
ZipFsStat.new(self, fileName)
|
||||
end
|
||||
|
||||
alias lstat stat
|
||||
|
||||
def readlines(fileName)
|
||||
open(fileName) { |is| is.readlines }
|
||||
end
|
||||
|
||||
def read(fileName)
|
||||
@mappedZip.read(fileName)
|
||||
end
|
||||
|
||||
def popen(*args, &aProc)
|
||||
File.popen(*args, &aProc)
|
||||
end
|
||||
|
||||
def foreach(fileName, aSep = $/, &aProc)
|
||||
open(fileName) { |is| is.each_line(aSep, &aProc) }
|
||||
end
|
||||
|
||||
def delete(*args)
|
||||
args.each {
|
||||
|fileName|
|
||||
if directory?(fileName)
|
||||
raise Errno::EISDIR, "Is a directory - \"#{fileName}\""
|
||||
end
|
||||
@mappedZip.remove(fileName)
|
||||
}
|
||||
end
|
||||
|
||||
def rename(fileToRename, newName)
|
||||
@mappedZip.rename(fileToRename, newName) { true }
|
||||
end
|
||||
|
||||
alias :unlink :delete
|
||||
|
||||
def expand_path(aPath)
|
||||
@mappedZip.expand_path(aPath)
|
||||
end
|
||||
end
|
||||
|
||||
# Instances of this class are normally accessed via the accessor
|
||||
# ZipFile::dir. An instance of ZipFsDir behaves like ruby's
|
||||
# builtin Dir (class) object, except it works on ZipFile entries.
|
||||
#
|
||||
# The individual methods are not documented due to their
|
||||
# similarity with the methods in Dir
|
||||
class ZipFsDir
|
||||
|
||||
def initialize(mappedZip)
|
||||
@mappedZip = mappedZip
|
||||
end
|
||||
|
||||
attr_writer :file
|
||||
|
||||
def new(aDirectoryName)
|
||||
ZipFsDirIterator.new(entries(aDirectoryName))
|
||||
end
|
||||
|
||||
def open(aDirectoryName)
|
||||
dirIt = new(aDirectoryName)
|
||||
if block_given?
|
||||
begin
|
||||
yield(dirIt)
|
||||
return nil
|
||||
ensure
|
||||
dirIt.close
|
||||
end
|
||||
end
|
||||
dirIt
|
||||
end
|
||||
|
||||
def pwd; @mappedZip.pwd; end
|
||||
alias getwd pwd
|
||||
|
||||
def chdir(aDirectoryName)
|
||||
unless @file.stat(aDirectoryName).directory?
|
||||
raise Errno::EINVAL, "Invalid argument - #{aDirectoryName}"
|
||||
end
|
||||
@mappedZip.pwd = @file.expand_path(aDirectoryName)
|
||||
end
|
||||
|
||||
def entries(aDirectoryName)
|
||||
entries = []
|
||||
foreach(aDirectoryName) { |e| entries << e }
|
||||
entries
|
||||
end
|
||||
|
||||
def foreach(aDirectoryName)
|
||||
unless @file.stat(aDirectoryName).directory?
|
||||
raise Errno::ENOTDIR, aDirectoryName
|
||||
end
|
||||
path = @file.expand_path(aDirectoryName).ensure_end("/")
|
||||
|
||||
subDirEntriesRegex = Regexp.new("^#{path}([^/]+)$")
|
||||
@mappedZip.each {
|
||||
|fileName|
|
||||
match = subDirEntriesRegex.match(fileName)
|
||||
yield(match[1]) unless match == nil
|
||||
}
|
||||
end
|
||||
|
||||
def delete(entryName)
|
||||
unless @file.stat(entryName).directory?
|
||||
raise Errno::EINVAL, "Invalid argument - #{entryName}"
|
||||
end
|
||||
@mappedZip.remove(entryName)
|
||||
end
|
||||
alias rmdir delete
|
||||
alias unlink delete
|
||||
|
||||
def mkdir(entryName, permissionInt = 0755)
|
||||
@mappedZip.mkdir(entryName, permissionInt)
|
||||
end
|
||||
|
||||
def chroot(*args)
|
||||
raise NotImplementedError, "The chroot() function is not implemented"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ZipFsDirIterator # :nodoc:all
|
||||
include Enumerable
|
||||
|
||||
def initialize(arrayOfFileNames)
|
||||
@fileNames = arrayOfFileNames
|
||||
@index = 0
|
||||
end
|
||||
|
||||
def close
|
||||
@fileNames = nil
|
||||
end
|
||||
|
||||
def each(&aProc)
|
||||
raise IOError, "closed directory" if @fileNames == nil
|
||||
@fileNames.each(&aProc)
|
||||
end
|
||||
|
||||
def read
|
||||
raise IOError, "closed directory" if @fileNames == nil
|
||||
@fileNames[(@index+=1)-1]
|
||||
end
|
||||
|
||||
def rewind
|
||||
raise IOError, "closed directory" if @fileNames == nil
|
||||
@index = 0
|
||||
end
|
||||
|
||||
def seek(anIntegerPosition)
|
||||
raise IOError, "closed directory" if @fileNames == nil
|
||||
@index = anIntegerPosition
|
||||
end
|
||||
|
||||
def tell
|
||||
raise IOError, "closed directory" if @fileNames == nil
|
||||
@index
|
||||
end
|
||||
end
|
||||
|
||||
# All access to ZipFile from ZipFsFile and ZipFsDir goes through a
|
||||
# ZipFileNameMapper, which has one responsibility: ensure
|
||||
class ZipFileNameMapper # :nodoc:all
|
||||
include Enumerable
|
||||
|
||||
def initialize(zipFile)
|
||||
@zipFile = zipFile
|
||||
@pwd = "/"
|
||||
end
|
||||
|
||||
attr_accessor :pwd
|
||||
|
||||
def find_entry(fileName)
|
||||
@zipFile.find_entry(expand_to_entry(fileName))
|
||||
end
|
||||
|
||||
def get_entry(fileName)
|
||||
@zipFile.get_entry(expand_to_entry(fileName))
|
||||
end
|
||||
|
||||
def get_input_stream(fileName, &aProc)
|
||||
@zipFile.get_input_stream(expand_to_entry(fileName), &aProc)
|
||||
end
|
||||
|
||||
def get_output_stream(fileName, &aProc)
|
||||
@zipFile.get_output_stream(expand_to_entry(fileName), &aProc)
|
||||
end
|
||||
|
||||
def read(fileName)
|
||||
@zipFile.read(expand_to_entry(fileName))
|
||||
end
|
||||
|
||||
def remove(fileName)
|
||||
@zipFile.remove(expand_to_entry(fileName))
|
||||
end
|
||||
|
||||
def rename(fileName, newName, &continueOnExistsProc)
|
||||
@zipFile.rename(expand_to_entry(fileName), expand_to_entry(newName),
|
||||
&continueOnExistsProc)
|
||||
end
|
||||
|
||||
def mkdir(fileName, permissionInt = 0755)
|
||||
@zipFile.mkdir(expand_to_entry(fileName), permissionInt)
|
||||
end
|
||||
|
||||
# Turns entries into strings and adds leading /
|
||||
# and removes trailing slash on directories
|
||||
def each
|
||||
@zipFile.each {
|
||||
|e|
|
||||
yield("/"+e.to_s.chomp("/"))
|
||||
}
|
||||
end
|
||||
|
||||
def expand_path(aPath)
|
||||
expanded = aPath.starts_with("/") ? aPath : @pwd.ensure_end("/") + aPath
|
||||
expanded.gsub!(/\/\.(\/|$)/, "")
|
||||
expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, "")
|
||||
expanded.empty? ? "/" : expanded
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def expand_to_entry(aPath)
|
||||
expand_path(aPath).lchop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ZipFile
|
||||
include ZipFileSystem
|
||||
end
|
||||
end
|
||||
|
||||
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
|
@ -1,90 +0,0 @@
|
|||
# With ziprequire you can load ruby modules from a zip file. This means
|
||||
# ruby's module include path can include zip-files.
|
||||
#
|
||||
# The following example creates a zip file with a single entry
|
||||
# <code>log/simplelog.rb</code> that contains a single function
|
||||
# <code>simpleLog</code>:
|
||||
#
|
||||
# require 'zip/zipfilesystem'
|
||||
#
|
||||
# Zip::ZipFile.open("my.zip", true) {
|
||||
# |zf|
|
||||
# zf.file.open("log/simplelog.rb", "w") {
|
||||
# |f|
|
||||
# f.puts "def simpleLog(v)"
|
||||
# f.puts ' Kernel.puts "INFO: #{v}"'
|
||||
# f.puts "end"
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# To use the ruby module stored in the zip archive simply require
|
||||
# <code>zip/ziprequire</code> and include the <code>my.zip</code> zip
|
||||
# file in the module search path. The following command shows one
|
||||
# way to do this:
|
||||
#
|
||||
# ruby -rzip/ziprequire -Imy.zip -e " require 'log/simplelog'; simpleLog 'Hello world' "
|
||||
|
||||
#$: << 'data/rubycode.zip' << 'data/rubycode2.zip'
|
||||
|
||||
|
||||
require 'zip/zip'
|
||||
|
||||
class ZipList #:nodoc:all
|
||||
def initialize(zipFileList)
|
||||
@zipFileList = zipFileList
|
||||
end
|
||||
|
||||
def get_input_stream(entry, &aProc)
|
||||
@zipFileList.each {
|
||||
|zfName|
|
||||
Zip::ZipFile.open(zfName) {
|
||||
|zf|
|
||||
begin
|
||||
return zf.get_input_stream(entry, &aProc)
|
||||
rescue Errno::ENOENT
|
||||
end
|
||||
}
|
||||
}
|
||||
raise Errno::ENOENT,
|
||||
"No matching entry found in zip files '#{@zipFileList.join(', ')}' "+
|
||||
" for '#{entry}'"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module Kernel #:nodoc:all
|
||||
alias :oldRequire :require
|
||||
|
||||
def require(moduleName)
|
||||
zip_require(moduleName) || oldRequire(moduleName)
|
||||
end
|
||||
|
||||
def zip_require(moduleName)
|
||||
return false if already_loaded?(moduleName)
|
||||
get_resource(ensure_rb_extension(moduleName)) {
|
||||
|zis|
|
||||
eval(zis.read); $" << moduleName
|
||||
}
|
||||
return true
|
||||
rescue Errno::ENOENT => ex
|
||||
return false
|
||||
end
|
||||
|
||||
def get_resource(resourceName, &aProc)
|
||||
zl = ZipList.new($:.grep(/\.zip$/))
|
||||
zl.get_input_stream(resourceName, &aProc)
|
||||
end
|
||||
|
||||
def already_loaded?(moduleName)
|
||||
moduleRE = Regexp.new("^"+moduleName+"(\.rb|\.so|\.dll|\.o)?$")
|
||||
$".detect { |e| e =~ moduleRE } != nil
|
||||
end
|
||||
|
||||
def ensure_rb_extension(aString)
|
||||
aString.sub(/(\.rb)?$/i, ".rb")
|
||||
end
|
||||
end
|
||||
|
||||
# Copyright (C) 2002 Thomas Sondergaard
|
||||
# rubyzip is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the ruby license.
|
Loading…
Reference in New Issue