ruzip 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.gitlab-ci.yml +14 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +6 -0
- data/MIT-LICENSE +7 -0
- data/README.md +35 -0
- data/Rakefile +21 -0
- data/ext/Cargo.lock +940 -0
- data/ext/Cargo.toml +13 -0
- data/ext/src/lib.rs +202 -0
- data/ruzip.gemspec +40 -0
- data/sig/ruzip.rbs +4 -0
- data/test/helper.rb +11 -0
- data/test/test_archive.rb +52 -0
- data/test/test_file.rb +16 -0
- data/test/test_ruzip.rb +7 -0
- metadata +160 -0
data/ext/Cargo.toml
ADDED
data/ext/src/lib.rs
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
use magnus::{
|
|
2
|
+
Error, Integer, RString, Ruby, Symbol, Value, class, exception, function, method, prelude::*,
|
|
3
|
+
};
|
|
4
|
+
use std::fs;
|
|
5
|
+
use std::io::{self, Read};
|
|
6
|
+
use std::os::fd::FromRawFd;
|
|
7
|
+
use std::sync::{Arc, Mutex};
|
|
8
|
+
use zip::ZipArchive;
|
|
9
|
+
|
|
10
|
+
type Result<T> = std::result::Result<T, Error>;
|
|
11
|
+
|
|
12
|
+
#[magnus::wrap(class = "RuZip::Archive", free_immediately, size)]
|
|
13
|
+
struct Archive(Arc<Mutex<ZipArchive<fs::File>>>);
|
|
14
|
+
|
|
15
|
+
struct IO(Value);
|
|
16
|
+
|
|
17
|
+
impl io::Read for IO {
|
|
18
|
+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
19
|
+
let buf_len = buf.len();
|
|
20
|
+
let r_string: Value = self.0.funcall_public("read", (buf_len,)).unwrap(); // FIXME: unwrap(). Should use second arg?
|
|
21
|
+
if r_string.is_nil() {
|
|
22
|
+
Ok(0)
|
|
23
|
+
} else {
|
|
24
|
+
let data = r_string.to_string();
|
|
25
|
+
let len = data.len();
|
|
26
|
+
buf.clone_from_slice(data.as_bytes()); // FIXME: clone_from_slice panics when sizes of buf and data are not the same
|
|
27
|
+
Ok(len)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
impl io::Seek for IO {
|
|
33
|
+
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
|
34
|
+
use io::SeekFrom::*;
|
|
35
|
+
let value = self.0;
|
|
36
|
+
|
|
37
|
+
match pos {
|
|
38
|
+
Start(i) => value
|
|
39
|
+
.funcall_public::<&str, (u64, Symbol), u64>("seek", (i, Symbol::new("SET")))
|
|
40
|
+
.unwrap(), // FIXME: unwrap()
|
|
41
|
+
End(i) => value
|
|
42
|
+
.funcall_public("seek", (i, Symbol::new("END")))
|
|
43
|
+
.unwrap(),
|
|
44
|
+
Current(i) => value
|
|
45
|
+
.funcall_public("seek", (i, Symbol::new("CUR")))
|
|
46
|
+
.unwrap(),
|
|
47
|
+
};
|
|
48
|
+
Ok(value.funcall_public("pos", ()).unwrap())
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
impl Archive {
|
|
53
|
+
fn new(r_io: Value) -> Result<Self> {
|
|
54
|
+
let io = if r_io.is_kind_of(class::io()) {
|
|
55
|
+
let fileno: Integer = r_io.funcall_public("fileno", ())?;
|
|
56
|
+
let raw_fd = fileno.to_i32()?;
|
|
57
|
+
unsafe { fs::File::from_raw_fd(raw_fd) }
|
|
58
|
+
} else if r_io.respond_to("to_path", false)? {
|
|
59
|
+
fs::File::open(
|
|
60
|
+
r_io.funcall_public::<&str, (), RString>("to_path", ())?
|
|
61
|
+
.to_string()?,
|
|
62
|
+
)
|
|
63
|
+
.unwrap()
|
|
64
|
+
} else if r_io.respond_to("read", false)? {
|
|
65
|
+
// IO(r_io);
|
|
66
|
+
todo!("#read");
|
|
67
|
+
} else if r_io.is_kind_of(class::string()) {
|
|
68
|
+
fs::File::open(r_io.to_r_string()?.to_string()?).unwrap() // FIXME: unwrap()
|
|
69
|
+
} else {
|
|
70
|
+
return Err(Error::new(
|
|
71
|
+
exception::type_error(),
|
|
72
|
+
format!("Unsupported argument type: {}", r_io.inspect()),
|
|
73
|
+
));
|
|
74
|
+
};
|
|
75
|
+
let zip: ZipArchive<fs::File> = ZipArchive::new(io)
|
|
76
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?;
|
|
77
|
+
Ok(Self(Arc::new(Mutex::new(zip))))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
fn len(&self) -> Result<usize> {
|
|
81
|
+
Ok(self
|
|
82
|
+
.0
|
|
83
|
+
.lock()
|
|
84
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
85
|
+
.len())
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
fn by_index(&self, index: usize) -> Result<File> {
|
|
89
|
+
match self
|
|
90
|
+
.0
|
|
91
|
+
.lock()
|
|
92
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
93
|
+
.by_index(index)
|
|
94
|
+
{
|
|
95
|
+
Ok(_) => Ok(File(self.0.clone(), index)),
|
|
96
|
+
Err(e) => Err(Error::new(exception::runtime_error(), format!("{}", e))),
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fn by_name(&self, name: RString) -> Result<Option<File>> {
|
|
101
|
+
let name_string = name
|
|
102
|
+
.to_string()
|
|
103
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?;
|
|
104
|
+
let mut archive = self
|
|
105
|
+
.0
|
|
106
|
+
.lock()
|
|
107
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?;
|
|
108
|
+
// TODO: Cache entries
|
|
109
|
+
for i in 0..archive.len() {
|
|
110
|
+
let file = archive
|
|
111
|
+
.by_index(i)
|
|
112
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?;
|
|
113
|
+
if file.name_raw() == name_string.clone().into_bytes() {
|
|
114
|
+
return Ok(Some(File(self.0.clone(), i)));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
Ok(None)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#[magnus::wrap(class = "RuZip::File")]
|
|
122
|
+
struct File(Arc<Mutex<ZipArchive<fs::File>>>, usize);
|
|
123
|
+
|
|
124
|
+
impl File {
|
|
125
|
+
// FIXME: exception::runtime_error() -> ruby.exception_runtime_error()
|
|
126
|
+
fn name(&self) -> Result<String> {
|
|
127
|
+
String::from_utf8(
|
|
128
|
+
self.0
|
|
129
|
+
.lock()
|
|
130
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
131
|
+
.by_index(self.1)
|
|
132
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
133
|
+
.name_raw()
|
|
134
|
+
.into(),
|
|
135
|
+
)
|
|
136
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
fn size(&self) -> Result<u64> {
|
|
140
|
+
let size = self
|
|
141
|
+
.0
|
|
142
|
+
.lock()
|
|
143
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
144
|
+
.by_index(self.1)
|
|
145
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
146
|
+
.size();
|
|
147
|
+
Ok(size)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// TODO: Use ExtendedTimestamp if available
|
|
151
|
+
fn last_modified(&self) -> Result<Option<Value>> {
|
|
152
|
+
let last_modified = self
|
|
153
|
+
.0
|
|
154
|
+
.lock()
|
|
155
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
156
|
+
.by_index(self.1)
|
|
157
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
158
|
+
.last_modified();
|
|
159
|
+
match last_modified {
|
|
160
|
+
Some(mtime) => Ok(Some(magnus::class::time().new_instance((
|
|
161
|
+
mtime.year(),
|
|
162
|
+
mtime.month(),
|
|
163
|
+
mtime.day(),
|
|
164
|
+
mtime.hour(),
|
|
165
|
+
mtime.minute(),
|
|
166
|
+
mtime.second(),
|
|
167
|
+
))?)),
|
|
168
|
+
None => Ok(None),
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
fn read(&self) -> Result<String> {
|
|
173
|
+
let mut buf = String::new();
|
|
174
|
+
self.0
|
|
175
|
+
.lock()
|
|
176
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
177
|
+
.by_index(self.1)
|
|
178
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?
|
|
179
|
+
.read_to_string(&mut buf)
|
|
180
|
+
.map_err(|e| Error::new(exception::runtime_error(), format!("{}", e)))?;
|
|
181
|
+
Ok(buf)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
#[magnus::init]
|
|
186
|
+
fn init(ruby: &Ruby) -> Result<()> {
|
|
187
|
+
let module = ruby.define_module("RuZip")?;
|
|
188
|
+
|
|
189
|
+
let archive_class = module.define_class("Archive", ruby.class_object())?;
|
|
190
|
+
archive_class.define_singleton_method("new", function!(Archive::new, 1))?;
|
|
191
|
+
archive_class.define_method("length", method!(Archive::len, 0))?;
|
|
192
|
+
|
|
193
|
+
let file_class = module.define_class("File", ruby.class_object())?;
|
|
194
|
+
archive_class.define_method("by_index", method!(Archive::by_index, 1))?;
|
|
195
|
+
archive_class.define_method("by_name", method!(Archive::by_name, 1))?;
|
|
196
|
+
file_class.define_method("name", method!(File::name, 0))?;
|
|
197
|
+
file_class.define_method("size", method!(File::size, 0))?;
|
|
198
|
+
file_class.define_method("last_modified", method!(File::last_modified, 0))?;
|
|
199
|
+
file_class.define_method("read", method!(File::read, 0))?;
|
|
200
|
+
|
|
201
|
+
Ok(())
|
|
202
|
+
}
|
data/ruzip.gemspec
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
rust_metadata = JSON.load(`cargo metadata --manifest-path=ext/Cargo.toml --no-deps --format-version=1`)
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "ruzip"
|
|
7
|
+
spec.version = rust_metadata["packages"][0]["version"]
|
|
8
|
+
spec.authors = ["Kitaiti Makoto"]
|
|
9
|
+
spec.email = ["KitaitiMakoto@gmail.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Library to support the reading and writing of zip files."
|
|
12
|
+
spec.description = "Library to support the reading and writing of zip files. A wrapper of Rust's zip crate."
|
|
13
|
+
spec.homepage = "https://gitlab.com/KitaitiMakoto/ruzip"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
spec.required_ruby_version = ">= 2.6.0"
|
|
16
|
+
spec.required_rubygems_version = ">= 3.3.11"
|
|
17
|
+
|
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
19
|
+
spec.metadata["source_code_uri"] = "https://gitlab.com/KitaitiMakoto/ruzip"
|
|
20
|
+
spec.metadata["changelog_uri"] = "https://gitlab.com/KitaitiMakoto/ruzip/-/blob/master/CHANGELOG.md"
|
|
21
|
+
|
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
24
|
+
spec.files = Dir.chdir(__dir__) do
|
|
25
|
+
`git ls-files -z`.split("\x0")
|
|
26
|
+
end
|
|
27
|
+
spec.require_paths = ["lib"]
|
|
28
|
+
spec.extensions = ["ext/Cargo.toml"]
|
|
29
|
+
|
|
30
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
31
|
+
spec.add_development_dependency "rake-compiler"
|
|
32
|
+
spec.add_development_dependency "test-unit", "~> 3.0"
|
|
33
|
+
spec.add_development_dependency "test-unit-notify"
|
|
34
|
+
spec.add_development_dependency "terminal-notifier"
|
|
35
|
+
spec.add_development_dependency "rubygems-tasks"
|
|
36
|
+
spec.add_development_dependency "kar"
|
|
37
|
+
|
|
38
|
+
# For more information and examples about making a new gem, check out our
|
|
39
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
|
40
|
+
end
|
data/sig/ruzip.rbs
ADDED
data/test/helper.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require_relative "helper"
|
|
2
|
+
|
|
3
|
+
class TestArchive < Test::Unit::TestCase
|
|
4
|
+
def setup
|
|
5
|
+
@fixture = fixture_path("accessible_epub_3.epub")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
test "new with path" do
|
|
9
|
+
archive = RuZip::Archive.new(@fixture)
|
|
10
|
+
assert_kind_of RuZip::Archive, archive
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test "new with pathname" do
|
|
14
|
+
archive = RuZip::Archive.new(Pathname(@fixture))
|
|
15
|
+
assert_kind_of RuZip::Archive, archive
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test "new with file" do
|
|
19
|
+
archive = RuZip::Archive.new(File.open(@fixture))
|
|
20
|
+
assert_kind_of RuZip::Archive, archive
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test "new with closed file" do
|
|
24
|
+
io = nil
|
|
25
|
+
File.open @fixture do |file|
|
|
26
|
+
io = file
|
|
27
|
+
end
|
|
28
|
+
assert_raise_kind_of IOError do
|
|
29
|
+
RuZip::Archive.new(io)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
test "new with string io" do
|
|
34
|
+
pend
|
|
35
|
+
|
|
36
|
+
require "stringio"
|
|
37
|
+
io = StringIO.new("EPUB file")
|
|
38
|
+
archive = RuZip::Archive.new(io)
|
|
39
|
+
assert_kind_of RuZip::Archive, archive
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test "new with unsupported type" do
|
|
43
|
+
assert_raise_kind_of TypeError do
|
|
44
|
+
RuZip::Archive.new(:symbol_object)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
test "len" do
|
|
49
|
+
archive = RuZip::Archive::new(@fixture)
|
|
50
|
+
assert_equal 38, archive.length
|
|
51
|
+
end
|
|
52
|
+
end
|
data/test/test_file.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require_relative "helper"
|
|
2
|
+
|
|
3
|
+
class TestFile < Test::Unit::TestCase
|
|
4
|
+
setup do
|
|
5
|
+
@archive = RuZip::Archive.new(fixture_path("accessible_epub_3.epub"))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
test "retrieve" do
|
|
9
|
+
file = @archive.by_name("META-INF/container.xml")
|
|
10
|
+
assert_instance_of RuZip::File, file
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test "retrieve non-existent" do
|
|
14
|
+
assert_nil @archive.by_name("non-existent")
|
|
15
|
+
end
|
|
16
|
+
end
|
data/test/test_ruzip.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ruzip
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kitaiti Makoto
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rake
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '13.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '13.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake-compiler
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: test-unit
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: test-unit-notify
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: terminal-notifier
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: rubygems-tasks
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: kar
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
description: Library to support the reading and writing of zip files. A wrapper of
|
|
111
|
+
Rust's zip crate.
|
|
112
|
+
email:
|
|
113
|
+
- KitaitiMakoto@gmail.com
|
|
114
|
+
executables: []
|
|
115
|
+
extensions:
|
|
116
|
+
- ext/Cargo.toml
|
|
117
|
+
extra_rdoc_files: []
|
|
118
|
+
files:
|
|
119
|
+
- ".gitignore"
|
|
120
|
+
- ".gitlab-ci.yml"
|
|
121
|
+
- CHANGELOG.md
|
|
122
|
+
- CODE_OF_CONDUCT.md
|
|
123
|
+
- Gemfile
|
|
124
|
+
- MIT-LICENSE
|
|
125
|
+
- README.md
|
|
126
|
+
- Rakefile
|
|
127
|
+
- ext/Cargo.lock
|
|
128
|
+
- ext/Cargo.toml
|
|
129
|
+
- ext/src/lib.rs
|
|
130
|
+
- ruzip.gemspec
|
|
131
|
+
- sig/ruzip.rbs
|
|
132
|
+
- test/helper.rb
|
|
133
|
+
- test/test_archive.rb
|
|
134
|
+
- test/test_file.rb
|
|
135
|
+
- test/test_ruzip.rb
|
|
136
|
+
homepage: https://gitlab.com/KitaitiMakoto/ruzip
|
|
137
|
+
licenses:
|
|
138
|
+
- MIT
|
|
139
|
+
metadata:
|
|
140
|
+
homepage_uri: https://gitlab.com/KitaitiMakoto/ruzip
|
|
141
|
+
source_code_uri: https://gitlab.com/KitaitiMakoto/ruzip
|
|
142
|
+
changelog_uri: https://gitlab.com/KitaitiMakoto/ruzip/-/blob/master/CHANGELOG.md
|
|
143
|
+
rdoc_options: []
|
|
144
|
+
require_paths:
|
|
145
|
+
- lib
|
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
|
+
requirements:
|
|
148
|
+
- - ">="
|
|
149
|
+
- !ruby/object:Gem::Version
|
|
150
|
+
version: 2.6.0
|
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
|
+
requirements:
|
|
153
|
+
- - ">="
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: 3.3.11
|
|
156
|
+
requirements: []
|
|
157
|
+
rubygems_version: 3.7.2
|
|
158
|
+
specification_version: 4
|
|
159
|
+
summary: Library to support the reading and writing of zip files.
|
|
160
|
+
test_files: []
|