zip_tricks 5.5.0 → 5.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +96 -0
- data/.gitignore +2 -1
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +4 -4
- data/README.md +2 -2
- data/lib/zip_tricks/rails_streaming.rb +1 -2
- data/lib/zip_tricks/streamer.rb +23 -10
- data/lib/zip_tricks/streamer/entry.rb +1 -1
- data/lib/zip_tricks/version.rb +1 -1
- data/lib/zip_tricks/zip_writer.rb +21 -21
- data/zip_tricks.gemspec +2 -4
- metadata +7 -34
- data/.travis.yml +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39403ce8cb20b4f772e5f44420b91be7e120df38b99de7de2a0db46f318760a8
|
4
|
+
data.tar.gz: c1c02357d9e5f322daf6d3ce338092020e753e362b3a70b3caf8d35a782925e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b16f5a53ee31ea9f1f5ec1316a62d172c897c510df9f1bb9f7fabe12aafe89e2b4e43f1533a01b5507b9d1a0fe438ee3646c7c10eb1117f8053403796167aad
|
7
|
+
data.tar.gz: 3808c09040d549644cb7aba6e8eb4aa0fcbae2123753e406d86db683e4e8d332453112622303be0b8027cff4c43dc60e6678073eb3e7c80cac3359200379210f
|
@@ -0,0 +1,96 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
- push
|
5
|
+
- pull_request
|
6
|
+
|
7
|
+
env:
|
8
|
+
BUNDLE_PATH: vendor/bundle
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
lint:
|
12
|
+
name: Code Style
|
13
|
+
runs-on: ubuntu-18.04
|
14
|
+
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
15
|
+
strategy:
|
16
|
+
matrix:
|
17
|
+
ruby:
|
18
|
+
- '2.7'
|
19
|
+
steps:
|
20
|
+
- name: Checkout
|
21
|
+
uses: actions/checkout@v2
|
22
|
+
- name: Setup Ruby
|
23
|
+
uses: ruby/setup-ruby@v1
|
24
|
+
with:
|
25
|
+
ruby-version: ${{ matrix.ruby }}
|
26
|
+
- name: Gemfile Cache
|
27
|
+
uses: actions/cache@v2
|
28
|
+
with:
|
29
|
+
path: Gemfile.lock
|
30
|
+
key: ${{ runner.os }}-gemlock-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'zip_tricks.gemspec') }}
|
31
|
+
restore-keys: |
|
32
|
+
${{ runner.os }}-gemlock-${{ matrix.ruby }}-
|
33
|
+
- name: Bundle Cache
|
34
|
+
id: cache-gems
|
35
|
+
uses: actions/cache@v2
|
36
|
+
with:
|
37
|
+
path: vendor/bundle
|
38
|
+
key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'Gemfile.lock', 'zip_tricks.gemspec') }}
|
39
|
+
restore-keys: |
|
40
|
+
${{ runner.os }}-gems-${{ matrix.ruby }}-
|
41
|
+
${{ runner.os }}-gems-
|
42
|
+
- name: Bundle Install
|
43
|
+
if: steps.cache-gems.outputs.cache-hit != 'true'
|
44
|
+
run: bundle install --jobs 4 --retry 3
|
45
|
+
- name: Rubocop Cache
|
46
|
+
uses: actions/cache@v2
|
47
|
+
with:
|
48
|
+
path: ~/.cache/rubocop_cache
|
49
|
+
key: ${{ runner.os }}-rubocop-${{ hashFiles('.rubocop.yml') }}
|
50
|
+
restore-keys: |
|
51
|
+
${{ runner.os }}-rubocop-
|
52
|
+
- name: Rubocop
|
53
|
+
run: bundle exec rubocop
|
54
|
+
test:
|
55
|
+
name: Specs
|
56
|
+
runs-on: ubuntu-18.04
|
57
|
+
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
58
|
+
strategy:
|
59
|
+
matrix:
|
60
|
+
ruby:
|
61
|
+
- '2.7'
|
62
|
+
- '2.1'
|
63
|
+
- 'jruby-9.2'
|
64
|
+
experimental: [false]
|
65
|
+
include:
|
66
|
+
- ruby: 3.0
|
67
|
+
experimental: true
|
68
|
+
steps:
|
69
|
+
- name: Checkout
|
70
|
+
uses: actions/checkout@v2
|
71
|
+
- name: Setup Ruby
|
72
|
+
uses: ruby/setup-ruby@v1
|
73
|
+
with:
|
74
|
+
ruby-version: ${{ matrix.ruby }}
|
75
|
+
- name: Gemfile Cache
|
76
|
+
uses: actions/cache@v2
|
77
|
+
with:
|
78
|
+
path: Gemfile.lock
|
79
|
+
key: ${{ runner.os }}-gemlock-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'zip_tricks.gemspec') }}
|
80
|
+
restore-keys: |
|
81
|
+
${{ runner.os }}-gemlock-${{ matrix.ruby }}-
|
82
|
+
- name: Bundle Cache
|
83
|
+
id: cache-gems
|
84
|
+
uses: actions/cache@v2
|
85
|
+
with:
|
86
|
+
path: vendor/bundle
|
87
|
+
key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'Gemfile.lock', 'zip_tricks.gemspec') }}
|
88
|
+
restore-keys: |
|
89
|
+
${{ runner.os }}-gems-${{ matrix.ruby }}-
|
90
|
+
${{ runner.os }}-gems-
|
91
|
+
- name: Bundle Install
|
92
|
+
if: steps.cache-gems.outputs.cache-hit != 'true'
|
93
|
+
run: bundle install --jobs 4 --retry 3
|
94
|
+
- name: RSpec
|
95
|
+
continue-on-error: ${{ matrix.experimental }}
|
96
|
+
run: bundle exec rspec
|
data/.gitignore
CHANGED
@@ -19,7 +19,7 @@ Gemfile.lock
|
|
19
19
|
# jeweler generated
|
20
20
|
pkg
|
21
21
|
|
22
|
-
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
22
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
23
23
|
#
|
24
24
|
# * Create a file at ~/.gitignore
|
25
25
|
# * Include files you want ignored
|
@@ -36,6 +36,7 @@ pkg
|
|
36
36
|
|
37
37
|
tmp
|
38
38
|
testing/*.zip
|
39
|
+
.ruby-version
|
39
40
|
|
40
41
|
# For TextMate
|
41
42
|
#*.tmproj
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 5.6.0
|
2
|
+
|
3
|
+
* Add customisable `unix_permissions` to Streamer and ZipWriter. Beware that customising these permissions can lead to the archive failing to expand with some unarchiving applications, and is especially sensitive for directories.
|
4
|
+
|
1
5
|
## 5.5.0
|
2
6
|
|
3
7
|
* In `OutputEnumerator` apply some amount of buffering to be within a UNIX socket size for metatada writes. This
|
data/CONTRIBUTING.md
CHANGED
@@ -27,7 +27,7 @@ The issue tracker is the preferred channel for [bug reports](#bug-reports),
|
|
27
27
|
[feature requests](#feature-requests) and [submitting pull
|
28
28
|
requests](#pull-requests), but please respect the following restrictions:
|
29
29
|
|
30
|
-
* Please **do not** derail or troll issues. Keep the discussion on topic and respect the opinions of others. Adhere to the principles set out in the [Code of Conduct](https://github.com/WeTransfer/zip_tricks/blob/
|
30
|
+
* Please **do not** derail or troll issues. Keep the discussion on topic and respect the opinions of others. Adhere to the principles set out in the [Code of Conduct](https://github.com/WeTransfer/zip_tricks/blob/main/CODE_OF_CONDUCT.md).
|
31
31
|
|
32
32
|
## Bug reports
|
33
33
|
|
@@ -41,7 +41,7 @@ Guidelines for bug reports:
|
|
41
41
|
reported.
|
42
42
|
|
43
43
|
2. **Check if the issue has been fixed** — try to reproduce it using the
|
44
|
-
latest `
|
44
|
+
latest `main` branch in the repository.
|
45
45
|
|
46
46
|
3. **Isolate the problem** — create a [reduced test
|
47
47
|
case](http://css-tricks.com/reduced-test-cases/) and a live example.
|
@@ -96,7 +96,7 @@ accurate comments, etc.) and any other requirements (such as test coverage).
|
|
96
96
|
The project uses Rubocop which can be run using `bundle exec rubocop`. The test
|
97
97
|
suite can be run with `bundle exec rspec`. You are also encouraged to use the
|
98
98
|
script in the `testing` directory to create test files that you can then verify
|
99
|
-
with various zip/unzip utilities. Further instructions are [here](https://github.com/WeTransfer/zip_tricks/blob/
|
99
|
+
with various zip/unzip utilities. Further instructions are [here](https://github.com/WeTransfer/zip_tricks/blob/main/testing/README_TESTING.md).
|
100
100
|
|
101
101
|
Follow this process if you'd like your work considered for inclusion in the
|
102
102
|
project:
|
@@ -148,4 +148,4 @@ project:
|
|
148
148
|
|
149
149
|
**IMPORTANT**: By submitting a patch, you agree to allow the project owner to
|
150
150
|
license your work under the same license as that used by the project, which you
|
151
|
-
can see by clicking [here](https://github.com/WeTransfer/zip_tricks/blob/
|
151
|
+
can see by clicking [here](https://github.com/WeTransfer/zip_tricks/blob/main/LICENSE.txt).
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# zip_tricks
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/WeTransfer/zip_tricks.svg?branch=
|
3
|
+
[![Build Status](https://travis-ci.org/WeTransfer/zip_tricks.svg?branch=main)](https://travis-ci.org/WeTransfer/zip_tricks)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/zip_tricks.svg)](https://badge.fury.io/rb/zip_tricks)
|
5
5
|
|
6
6
|
Allows streaming, non-rewinding ZIP file output from Ruby.
|
@@ -175,7 +175,7 @@ that have not been formally verified (ours hasn't been).
|
|
175
175
|
|
176
176
|
## Contributing to zip_tricks
|
177
177
|
|
178
|
-
* Check out the latest
|
178
|
+
* Check out the latest `main` to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
179
179
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
180
180
|
* Fork the project.
|
181
181
|
* Start a feature/bugfix branch.
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Should be included into a Rails controller
|
4
|
-
# for easy ZIP output from any action.
|
3
|
+
# Should be included into a Rails controller for easy ZIP output from any action.
|
5
4
|
module ZipTricks::RailsStreaming
|
6
5
|
# Opens a {ZipTricks::Streamer} and yields it to the caller. The output of the streamer
|
7
6
|
# gets automatically forwarded to the Rails response stream. When the output completes,
|
data/lib/zip_tricks/streamer.rb
CHANGED
@@ -200,14 +200,16 @@ class ZipTricks::Streamer
|
|
200
200
|
# @param uncompressed_size [Integer] the size of the entry when uncompressed, in bytes
|
201
201
|
# @param crc32 [Integer] the CRC32 checksum of the entry when uncompressed
|
202
202
|
# @param use_data_descriptor [Boolean] whether the entry body will be followed by a data descriptor
|
203
|
+
# @param unix_permissions[Fixnum?] which UNIX permissions to set, normally the default should be used
|
203
204
|
# @return [Integer] the offset the output IO is at after writing the entry header
|
204
|
-
def add_deflated_entry(filename:, modification_time: Time.now.utc, compressed_size: 0, uncompressed_size: 0, crc32: 0, use_data_descriptor: false)
|
205
|
+
def add_deflated_entry(filename:, modification_time: Time.now.utc, compressed_size: 0, uncompressed_size: 0, crc32: 0, unix_permissions: nil, use_data_descriptor: false)
|
205
206
|
add_file_and_write_local_header(filename: filename,
|
206
207
|
modification_time: modification_time,
|
207
208
|
crc32: crc32,
|
208
209
|
storage_mode: DEFLATED,
|
209
210
|
compressed_size: compressed_size,
|
210
211
|
uncompressed_size: uncompressed_size,
|
212
|
+
unix_permissions: unix_permissions,
|
211
213
|
use_data_descriptor: use_data_descriptor)
|
212
214
|
@out.tell
|
213
215
|
end
|
@@ -222,14 +224,16 @@ class ZipTricks::Streamer
|
|
222
224
|
# @param size [Integer] the size of the file when uncompressed, in bytes
|
223
225
|
# @param crc32 [Integer] the CRC32 checksum of the entry when uncompressed
|
224
226
|
# @param use_data_descriptor [Boolean] whether the entry body will be followed by a data descriptor. When in use
|
227
|
+
# @param unix_permissions[Fixnum?] which UNIX permissions to set, normally the default should be used
|
225
228
|
# @return [Integer] the offset the output IO is at after writing the entry header
|
226
|
-
def add_stored_entry(filename:, modification_time: Time.now.utc, size: 0, crc32: 0, use_data_descriptor: false)
|
229
|
+
def add_stored_entry(filename:, modification_time: Time.now.utc, size: 0, crc32: 0, unix_permissions: nil, use_data_descriptor: false)
|
227
230
|
add_file_and_write_local_header(filename: filename,
|
228
231
|
modification_time: modification_time,
|
229
232
|
crc32: crc32,
|
230
233
|
storage_mode: STORED,
|
231
234
|
compressed_size: size,
|
232
235
|
uncompressed_size: size,
|
236
|
+
unix_permissions: unix_permissions,
|
233
237
|
use_data_descriptor: use_data_descriptor)
|
234
238
|
@out.tell
|
235
239
|
end
|
@@ -238,14 +242,16 @@ class ZipTricks::Streamer
|
|
238
242
|
#
|
239
243
|
# @param dirname [String] the name of the directory in the archive
|
240
244
|
# @param modification_time [Time] the modification time of the directory in the archive
|
245
|
+
# @param unix_permissions[Fixnum?] which UNIX permissions to set, normally the default should be used
|
241
246
|
# @return [Integer] the offset the output IO is at after writing the entry header
|
242
|
-
def add_empty_directory(dirname:, modification_time: Time.now.utc)
|
247
|
+
def add_empty_directory(dirname:, modification_time: Time.now.utc, unix_permissions: nil)
|
243
248
|
add_file_and_write_local_header(filename: dirname.to_s + '/',
|
244
249
|
modification_time: modification_time,
|
245
250
|
crc32: 0,
|
246
251
|
storage_mode: STORED,
|
247
252
|
compressed_size: 0,
|
248
253
|
uncompressed_size: 0,
|
254
|
+
unix_permissions: unix_permissions,
|
249
255
|
use_data_descriptor: false)
|
250
256
|
@out.tell
|
251
257
|
end
|
@@ -283,14 +289,16 @@ class ZipTricks::Streamer
|
|
283
289
|
#
|
284
290
|
# @param filename[String] the name of the file in the archive
|
285
291
|
# @param modification_time [Time] the modification time of the file in the archive
|
292
|
+
# @param unix_permissions[Fixnum?] which UNIX permissions to set, normally the default should be used
|
286
293
|
# @yield [#<<, #write] an object that the file contents must be written to that will be automatically closed
|
287
294
|
# @return [#<<, #write, #close] an object that the file contents must be written to, has to be closed manually
|
288
|
-
def write_stored_file(filename, modification_time: Time.now.utc)
|
295
|
+
def write_stored_file(filename, modification_time: Time.now.utc, unix_permissions: nil)
|
289
296
|
add_stored_entry(filename: filename,
|
290
297
|
modification_time: modification_time,
|
291
298
|
use_data_descriptor: true,
|
292
299
|
crc32: 0,
|
293
|
-
size: 0
|
300
|
+
size: 0,
|
301
|
+
unix_permissions: unix_permissions)
|
294
302
|
|
295
303
|
writable = Writable.new(self, StoredWriter.new(@out))
|
296
304
|
if block_given?
|
@@ -335,14 +343,16 @@ class ZipTricks::Streamer
|
|
335
343
|
#
|
336
344
|
# @param filename[String] the name of the file in the archive
|
337
345
|
# @param modification_time [Time] the modification time of the file in the archive
|
346
|
+
# @param unix_permissions[Fixnum?] which UNIX permissions to set, normally the default should be used
|
338
347
|
# @yield [#<<, #write] an object that the file contents must be written to
|
339
|
-
def write_deflated_file(filename, modification_time: Time.now.utc)
|
348
|
+
def write_deflated_file(filename, modification_time: Time.now.utc, unix_permissions: nil)
|
340
349
|
add_deflated_entry(filename: filename,
|
341
350
|
modification_time: modification_time,
|
342
351
|
use_data_descriptor: true,
|
343
352
|
crc32: 0,
|
344
353
|
compressed_size: 0,
|
345
|
-
uncompressed_size: 0
|
354
|
+
uncompressed_size: 0,
|
355
|
+
unix_permissions: unix_permissions)
|
346
356
|
|
347
357
|
writable = Writable.new(self, DeflatedWriter.new(@out))
|
348
358
|
if block_given?
|
@@ -375,7 +385,8 @@ class ZipTricks::Streamer
|
|
375
385
|
uncompressed_size: entry.uncompressed_size,
|
376
386
|
mtime: entry.mtime,
|
377
387
|
crc32: entry.crc32,
|
378
|
-
filename: entry.filename
|
388
|
+
filename: entry.filename,
|
389
|
+
unix_permissions: entry.unix_permissions)
|
379
390
|
end
|
380
391
|
|
381
392
|
# Record the central directory size, for the EOCDR
|
@@ -462,7 +473,8 @@ EMS
|
|
462
473
|
storage_mode:,
|
463
474
|
compressed_size:,
|
464
475
|
uncompressed_size:,
|
465
|
-
use_data_descriptor
|
476
|
+
use_data_descriptor:,
|
477
|
+
unix_permissions:)
|
466
478
|
|
467
479
|
# Clean backslashes
|
468
480
|
filename = remove_backslash(filename)
|
@@ -498,7 +510,8 @@ EMS
|
|
498
510
|
use_data_descriptor,
|
499
511
|
_local_file_header_offset = local_header_starts_at,
|
500
512
|
_bytes_used_for_local_header = 0,
|
501
|
-
_bytes_used_for_data_descriptor = 0
|
513
|
+
_bytes_used_for_data_descriptor = 0,
|
514
|
+
unix_permissions)
|
502
515
|
|
503
516
|
@writer.write_local_file_header(io: @out,
|
504
517
|
gp_flags: e.gp_flags,
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Normally you will not have to use this class directly
|
5
5
|
class ZipTricks::Streamer::Entry < Struct.new(:filename, :crc32, :compressed_size,
|
6
6
|
:uncompressed_size, :storage_mode, :mtime,
|
7
|
-
:use_data_descriptor, :local_header_offset, :bytes_used_for_local_header, :bytes_used_for_data_descriptor)
|
7
|
+
:use_data_descriptor, :local_header_offset, :bytes_used_for_local_header, :bytes_used_for_data_descriptor, :unix_permissions)
|
8
8
|
def initialize(*)
|
9
9
|
super
|
10
10
|
filename.force_encoding(Encoding::UTF_8)
|
data/lib/zip_tricks/version.rb
CHANGED
@@ -31,22 +31,10 @@ class ZipTricks::ZipWriter
|
|
31
31
|
VERSION_MADE_BY = 52
|
32
32
|
VERSION_NEEDED_TO_EXTRACT = 20
|
33
33
|
VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# zipinfo.external_attr = 0644 << 16L # permissions -r-wr--r--.
|
39
|
-
# We snatch the incantations from Rubyzip for this.
|
40
|
-
unix_perms = 0o644
|
41
|
-
file_type_file = 0o10
|
42
|
-
(file_type_file << 12 | (unix_perms & 0o7777)) << 16
|
43
|
-
end
|
44
|
-
EMPTY_DIRECTORY_EXTERNAL_ATTRS = begin
|
45
|
-
# Applies permissions to an empty directory.
|
46
|
-
unix_perms = 0o755
|
47
|
-
file_type_dir = 0o04
|
48
|
-
(file_type_dir << 12 | (unix_perms & 0o7777)) << 16
|
49
|
-
end
|
34
|
+
DEFAULT_FILE_UNIX_PERMISSIONS = 0o644
|
35
|
+
DEFAULT_DIRECTORY_UNIX_PERMISSIONS = 0o755
|
36
|
+
FILE_TYPE_FILE = 0o10
|
37
|
+
FILE_TYPE_DIRECTORY = 0o04
|
50
38
|
MADE_BY_SIGNATURE = begin
|
51
39
|
# A combination of the VERSION_MADE_BY low byte and the OS type high byte
|
52
40
|
os_type = 3 # UNIX
|
@@ -64,7 +52,8 @@ class ZipTricks::ZipWriter
|
|
64
52
|
:VERSION_MADE_BY,
|
65
53
|
:VERSION_NEEDED_TO_EXTRACT,
|
66
54
|
:VERSION_NEEDED_TO_EXTRACT_ZIP64,
|
67
|
-
:
|
55
|
+
:FILE_TYPE_FILE,
|
56
|
+
:FILE_TYPE_DIRECTORY,
|
68
57
|
:MADE_BY_SIGNATURE,
|
69
58
|
:C_UINT4,
|
70
59
|
:C_UINT2,
|
@@ -136,6 +125,7 @@ class ZipTricks::ZipWriter
|
|
136
125
|
# @param crc32[Fixnum] The CRC32 checksum of the file
|
137
126
|
# @param mtime[Time] the modification time to be recorded in the ZIP
|
138
127
|
# @param gp_flags[Fixnum] bit-packed general purpose flags
|
128
|
+
# @param unix_permissions[Fixnum?] the permissions for the file, or nil for the default to be used
|
139
129
|
# @return [void]
|
140
130
|
def write_central_directory_file_header(io:,
|
141
131
|
local_file_header_location:,
|
@@ -145,7 +135,9 @@ class ZipTricks::ZipWriter
|
|
145
135
|
uncompressed_size:,
|
146
136
|
mtime:,
|
147
137
|
crc32:,
|
148
|
-
filename
|
138
|
+
filename:,
|
139
|
+
unix_permissions: nil
|
140
|
+
)
|
149
141
|
# At this point if the header begins somewhere beyound 0xFFFFFFFF we _have_ to record the offset
|
150
142
|
# of the local file header as a zip64 extra field, so we give up, give in, you loose, love will always win...
|
151
143
|
add_zip64 = (local_file_header_location > FOUR_BYTE_MAX_UINT) ||
|
@@ -200,11 +192,15 @@ class ZipTricks::ZipWriter
|
|
200
192
|
|
201
193
|
# Because the add_empty_directory method will create a directory with a trailing "/",
|
202
194
|
# this check can be used to assign proper permissions to the created directory.
|
203
|
-
|
204
|
-
|
195
|
+
# external file attributes 4 bytes
|
196
|
+
external_attrs = if filename.end_with?('/')
|
197
|
+
unix_permissions ||= DEFAULT_DIRECTORY_UNIX_PERMISSIONS
|
198
|
+
generate_external_attrs(unix_permissions, FILE_TYPE_DIRECTORY)
|
205
199
|
else
|
206
|
-
|
200
|
+
unix_permissions ||= DEFAULT_FILE_UNIX_PERMISSIONS
|
201
|
+
generate_external_attrs(unix_permissions, FILE_TYPE_FILE)
|
207
202
|
end
|
203
|
+
io << [external_attrs].pack(C_UINT4)
|
208
204
|
|
209
205
|
io << if add_zip64 # relative offset of local header 4 bytes
|
210
206
|
[FOUR_BYTE_MAX_UINT].pack(C_UINT4)
|
@@ -434,4 +430,8 @@ class ZipTricks::ZipWriter
|
|
434
430
|
values, packspecs = values_to_packspecs.partition.each_with_index { |_, i| i.even? }
|
435
431
|
values.pack(packspecs.join)
|
436
432
|
end
|
433
|
+
|
434
|
+
def generate_external_attrs(unix_permissions_int, file_type_int)
|
435
|
+
(file_type_int << 12 | (unix_permissions_int & 0o7777)) << 16
|
436
|
+
end
|
437
437
|
end
|
data/zip_tricks.gemspec
CHANGED
@@ -5,7 +5,7 @@ require 'zip_tricks/version'
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'zip_tricks'
|
7
7
|
spec.version = ZipTricks::VERSION
|
8
|
-
spec.authors = ['Julik Tarkhanov', 'Noah Berman', 'Dmitry Tymchuk', 'David Bosveld']
|
8
|
+
spec.authors = ['Julik Tarkhanov', 'Noah Berman', 'Dmitry Tymchuk', 'David Bosveld', 'Felix Bünemann']
|
9
9
|
spec.email = ['me@julik.nl']
|
10
10
|
|
11
11
|
spec.licenses = ['MIT (Hippocratic)']
|
@@ -32,10 +32,8 @@ Gem::Specification.new do |spec|
|
|
32
32
|
|
33
33
|
spec.add_development_dependency 'bundler'
|
34
34
|
spec.add_development_dependency 'rubyzip', '~> 1'
|
35
|
-
spec.add_development_dependency 'terminal-table'
|
36
|
-
spec.add_development_dependency 'range_utils'
|
37
35
|
|
38
|
-
spec.add_development_dependency 'rack', '~> 1.6' # For
|
36
|
+
spec.add_development_dependency 'rack', '~> 1.6' # For tests, where we spin up a server
|
39
37
|
spec.add_development_dependency 'rake', '~> 12.2'
|
40
38
|
spec.add_development_dependency 'rspec', '~> 3'
|
41
39
|
spec.add_development_dependency 'complexity_assert'
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zip_tricks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
- Noah Berman
|
9
9
|
- Dmitry Tymchuk
|
10
10
|
- David Bosveld
|
11
|
-
|
11
|
+
- Felix Bünemann
|
12
|
+
autorequire:
|
12
13
|
bindir: exe
|
13
14
|
cert_chain: []
|
14
|
-
date:
|
15
|
+
date: 2021-06-05 00:00:00.000000000 Z
|
15
16
|
dependencies:
|
16
17
|
- !ruby/object:Gem::Dependency
|
17
18
|
name: bundler
|
@@ -41,34 +42,6 @@ dependencies:
|
|
41
42
|
- - "~>"
|
42
43
|
- !ruby/object:Gem::Version
|
43
44
|
version: '1'
|
44
|
-
- !ruby/object:Gem::Dependency
|
45
|
-
name: terminal-table
|
46
|
-
requirement: !ruby/object:Gem::Requirement
|
47
|
-
requirements:
|
48
|
-
- - ">="
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
version: '0'
|
51
|
-
type: :development
|
52
|
-
prerelease: false
|
53
|
-
version_requirements: !ruby/object:Gem::Requirement
|
54
|
-
requirements:
|
55
|
-
- - ">="
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: '0'
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: range_utils
|
60
|
-
requirement: !ruby/object:Gem::Requirement
|
61
|
-
requirements:
|
62
|
-
- - ">="
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
version: '0'
|
65
|
-
type: :development
|
66
|
-
prerelease: false
|
67
|
-
version_requirements: !ruby/object:Gem::Requirement
|
68
|
-
requirements:
|
69
|
-
- - ">="
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
version: '0'
|
72
45
|
- !ruby/object:Gem::Dependency
|
73
46
|
name: rack
|
74
47
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,10 +191,10 @@ extra_rdoc_files: []
|
|
218
191
|
files:
|
219
192
|
- ".codeclimate.yml"
|
220
193
|
- ".document"
|
194
|
+
- ".github/workflows/ci.yml"
|
221
195
|
- ".gitignore"
|
222
196
|
- ".rspec"
|
223
197
|
- ".rubocop.yml"
|
224
|
-
- ".travis.yml"
|
225
198
|
- ".yardopts"
|
226
199
|
- CHANGELOG.md
|
227
200
|
- CODE_OF_CONDUCT.md
|
@@ -268,7 +241,7 @@ licenses:
|
|
268
241
|
- MIT (Hippocratic)
|
269
242
|
metadata:
|
270
243
|
allowed_push_host: https://rubygems.org
|
271
|
-
post_install_message:
|
244
|
+
post_install_message:
|
272
245
|
rdoc_options: []
|
273
246
|
require_paths:
|
274
247
|
- lib
|
@@ -284,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
284
257
|
version: '0'
|
285
258
|
requirements: []
|
286
259
|
rubygems_version: 3.0.3
|
287
|
-
signing_key:
|
260
|
+
signing_key:
|
288
261
|
specification_version: 4
|
289
262
|
summary: Stream out ZIP files from Ruby
|
290
263
|
test_files: []
|