ngzip 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +16 -1
- data/Gemfile +8 -0
- data/LICENSE.txt +1 -0
- data/README.md +2 -2
- data/Rakefile +6 -4
- data/lib/ngzip.rb +6 -3
- data/lib/ngzip/builder.rb +59 -49
- data/lib/ngzip/version.rb +3 -1
- data/ngzip.gemspec +17 -14
- data/test/data/a/d/my_file.txt +1 -0
- data/test/data/a/filename-without-a-dot +1 -0
- data/test/data/c/A filename with space and + in it.txt +1 -0
- data/test/data/c/questions?/test.txt +1 -0
- data/test/lib/ngzip/builder_test.rb +117 -78
- data/test/lib/ngzip/version_test.rb +6 -6
- data/test/test_helper.rb +6 -2
- metadata +41 -32
- data/.rvmrc +0 -48
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 84899280f348b240160b5c6984b7a4130a7a48f71b9c7d903051f99a36326f09
|
4
|
+
data.tar.gz: 1b1b057b9da9d80900035e732ed586b13c9e5a25659b4b9ac226862f7d6782b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f5b599664e6b4f49de86596596ae5bdae4f9ab8601c260e58e075c6376d6a37c5aa25a441baa971cf590a1b11d218e675369e67140ca9076df197fc2c62aeaa
|
7
|
+
data.tar.gz: 815fb0735456a2020781276b456c47e8e76d567e2ef8b35bcd65856e38913c55e00c717cb1a0ced8da4f8e39d1d9febf9deec9645dcb9d2bf4de2790520ddee1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
### 1.0.7 (2017-10-20)
|
2
|
+
|
3
|
+
* Fixed an issue with '?' encoding
|
4
|
+
|
5
|
+
### 1.0.6 (2013-12-12)
|
6
|
+
|
7
|
+
* Fixed a regression from 1.0.5 where directories were included due to the changed pattern
|
8
|
+
|
9
|
+
### 1.0.5 (2013-12-12)
|
10
|
+
|
11
|
+
* Fixed issue #2 (files without extensions being ignored)
|
12
|
+
|
13
|
+
### 1.0.4 (2013-09-20)
|
14
|
+
|
15
|
+
* Fixed issue #1 ("+" character in filename)
|
16
|
+
|
1
17
|
### 1.0.3 (2013-08-05)
|
2
18
|
|
3
19
|
* Added the :base_dir option
|
@@ -13,4 +29,3 @@
|
|
13
29
|
### 1.0.0 (2013-07-14)
|
14
30
|
|
15
31
|
* Initial public release
|
16
|
-
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -22,7 +22,7 @@ Or install it yourself as:
|
|
22
22
|
In a controller
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
b =
|
25
|
+
b = Ngzip::Builder.new()
|
26
26
|
response.headers['X-Archive-Files'] = 'zip'
|
27
27
|
render :text => b.build(["/data/test/Report.pdf", "/data/test/LargeArchive.tar"])
|
28
28
|
```
|
@@ -67,6 +67,6 @@ fetch the actual file data and would support any location type (even proxied).
|
|
67
67
|
## License
|
68
68
|
|
69
69
|
Copyright (c) 2013, ncode gmbh. All Rights Reserved.
|
70
|
+
Copyright (c) 2017, CargoServer AG. All Rights Reserved.
|
70
71
|
|
71
72
|
This project is licenced under the [MIT License](LICENSE.txt).
|
72
|
-
|
data/Rakefile
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
require 'rake/testtask'
|
4
6
|
|
5
7
|
Rake::TestTask.new do |t|
|
6
8
|
t.libs << 'lib'
|
7
9
|
t.test_files = FileList['test/lib/ngzip/*_test.rb']
|
8
10
|
t.verbose = true
|
9
11
|
end
|
10
|
-
|
11
|
-
task :
|
12
|
+
|
13
|
+
task default: :test
|
data/lib/ngzip.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
|
2
|
-
require "ngzip/builder"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
3
|
+
require 'ngzip/version'
|
4
|
+
require 'ngzip/builder'
|
5
|
+
|
6
|
+
# Ngzip module
|
4
7
|
module Ngzip
|
5
8
|
def self.build(files, options)
|
6
|
-
Ngzip::Builder.new
|
9
|
+
Ngzip::Builder.new.build(files, options)
|
7
10
|
end
|
8
11
|
end
|
data/lib/ngzip/builder.rb
CHANGED
@@ -1,105 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'zlib'
|
2
4
|
require 'uri'
|
5
|
+
require 'erb'
|
3
6
|
|
4
7
|
module Ngzip
|
5
|
-
|
8
|
+
# The manifest builder based on the file list
|
6
9
|
class Builder
|
7
|
-
|
8
10
|
BUFFER_SIZE = 8 * 1024
|
9
|
-
|
11
|
+
|
10
12
|
# Public: Build the files manifest for mod_zip, see http://wiki.nginx.org/NginxNgxZip for the specs.
|
11
|
-
#
|
13
|
+
#
|
12
14
|
# files - An Array of absolute file path elements
|
13
15
|
# options - The options, see below
|
14
|
-
#
|
16
|
+
#
|
15
17
|
# Returns a line for each file separated by \n
|
16
|
-
#
|
18
|
+
#
|
17
19
|
# The following options are available:
|
18
|
-
# :
|
19
|
-
# :
|
20
|
-
# :
|
20
|
+
# crc: Enable or disable CRC-32 checksums
|
21
|
+
# crc_cache: Allows for provided cached CRC-32 checksums in a hash where the key is the file path
|
22
|
+
# base_dir: Use this as root for the relative pathes in the archive, keep all directories below
|
21
23
|
def build(files, options = {})
|
22
|
-
settings = {:
|
24
|
+
settings = { crc: true }
|
23
25
|
settings.merge! options
|
24
|
-
|
26
|
+
|
25
27
|
list = file_list(files)
|
26
28
|
prefix = options[:base_dir] || detect_common_prefix(list)
|
27
29
|
prefix += '/' unless prefix.end_with?('/')
|
28
30
|
list.map do |f|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
format(
|
32
|
+
'%<crc>s %<size>d %<url>s %<name>s',
|
33
|
+
{
|
34
|
+
crc: compute_crc32(f, settings),
|
35
|
+
size: File.size(f).to_i,
|
36
|
+
url: Builder.encode(f),
|
37
|
+
name: f.gsub(prefix, '')
|
38
|
+
}
|
34
39
|
)
|
35
40
|
end.join("\n")
|
36
41
|
end
|
37
42
|
|
38
43
|
# Public: Get the special header to signal the mod_zip
|
39
|
-
#
|
44
|
+
#
|
40
45
|
# Returns the header as a string "key: value"
|
41
|
-
def header
|
42
|
-
|
46
|
+
def header
|
47
|
+
'X-Archive-Files: zip'
|
48
|
+
end
|
49
|
+
|
50
|
+
# Public: Encode the string
|
51
|
+
#
|
52
|
+
# Returns the encoded string using URL escape formatting
|
53
|
+
def self.encode(string)
|
54
|
+
ERB::Util.url_encode(string)
|
43
55
|
end
|
44
|
-
|
56
|
+
|
45
57
|
private
|
46
|
-
|
58
|
+
|
47
59
|
# Internal: Compute a common prefix from a list of path elements
|
48
|
-
#
|
60
|
+
#
|
49
61
|
# list - The list of file path elements
|
50
|
-
#
|
62
|
+
#
|
51
63
|
# Returns a common prefix
|
52
64
|
def detect_common_prefix(list)
|
53
|
-
if list.size == 1
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
min, max =
|
65
|
+
return File.dirname(list.first) if list.size == 1
|
66
|
+
|
67
|
+
prefix = StringIO.new
|
68
|
+
excluding_file_names = list.map { |p| File.dirname p }
|
69
|
+
min, max = excluding_file_names.sort.values_at(0, -1)
|
58
70
|
min.split(//).each_with_index do |c, i|
|
59
71
|
break if c != max[i, 1]
|
72
|
+
|
60
73
|
prefix << c
|
61
74
|
end
|
62
|
-
prefix
|
75
|
+
prefix.string
|
63
76
|
end
|
64
|
-
|
77
|
+
|
65
78
|
# Internal: Compute the file list by expanding directories
|
66
|
-
#
|
79
|
+
#
|
67
80
|
def file_list(files)
|
68
81
|
Array(files).map do |e|
|
69
82
|
if File.directory?(e)
|
70
|
-
|
83
|
+
# `expand_path` removes any trailing slash from the path string
|
84
|
+
sanitized_path = File.expand_path(e)
|
85
|
+
Dir.glob("#{sanitized_path}/**/*").reject { |f| File.directory?(f) }
|
71
86
|
else
|
72
87
|
e
|
73
88
|
end
|
74
89
|
end.flatten
|
75
90
|
end
|
76
|
-
|
77
|
-
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
91
|
+
|
92
|
+
# Internal: Compute the CRC-32 checksum for a file unless the settings
|
93
|
+
# disable the computation (crc: false) and this method returns "-"
|
94
|
+
#
|
81
95
|
# file - The full path to the file
|
82
96
|
# settings - The settings hash
|
83
|
-
#
|
97
|
+
#
|
84
98
|
# Returns a hex string
|
85
99
|
def compute_crc32(file, settings)
|
86
100
|
return '-' unless settings[:crc]
|
87
|
-
|
101
|
+
|
88
102
|
# honor the cache
|
89
|
-
if settings[:crc_cache] && settings[:crc_cache][file]
|
90
|
-
|
91
|
-
end
|
92
|
-
|
103
|
+
return settings[:crc_cache][file] if settings[:crc_cache] && settings[:crc_cache][file]
|
104
|
+
|
93
105
|
# read using a buffer, we might operate on large files!
|
94
106
|
crc32 = 0
|
95
|
-
File.open(file,'rb') do |f|
|
96
|
-
while buffer = f.read(BUFFER_SIZE)
|
97
|
-
crc32 = Zlib.crc32(buffer, crc32)
|
107
|
+
File.open(file, 'rb') do |f|
|
108
|
+
while (buffer = f.read(BUFFER_SIZE))
|
109
|
+
crc32 = Zlib.crc32(buffer, crc32)
|
98
110
|
end
|
99
111
|
end
|
100
112
|
crc32.to_s(16)
|
101
113
|
end
|
102
|
-
|
103
114
|
end
|
104
|
-
|
105
|
-
end
|
115
|
+
end
|
data/lib/ngzip/version.rb
CHANGED
data/ngzip.gemspec
CHANGED
@@ -1,24 +1,27 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'english'
|
4
6
|
require 'ngzip/version'
|
5
7
|
|
6
8
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
9
|
+
spec.name = 'ngzip'
|
8
10
|
spec.version = Ngzip::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description = %
|
12
|
-
See http://wiki.nginx.org/NginxNgxZip for the nginx module.
|
13
|
-
spec.summary =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
11
|
+
spec.authors = ['dup2']
|
12
|
+
spec.email = ['zarkov@cargoserver.ch']
|
13
|
+
spec.description = %(Provides a nginx mod_zip compatible file manifest for streaming support.
|
14
|
+
See http://wiki.nginx.org/NginxNgxZip for the nginx module.)
|
15
|
+
spec.summary = 'Provides a nginx mod_zip compatible file manifest for streaming support'
|
16
|
+
spec.homepage = 'https://github.com/cargoserver/ngzip'
|
17
|
+
spec.license = 'MIT'
|
16
18
|
|
17
|
-
spec.files = `git ls-files`.split(
|
19
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
18
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
21
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = ['lib']
|
21
23
|
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'rubocop'
|
24
27
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
@@ -0,0 +1 @@
|
|
1
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
@@ -0,0 +1 @@
|
|
1
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
@@ -0,0 +1 @@
|
|
1
|
+
Tyrell Corp.
|
@@ -1,115 +1,154 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../test_helper'
|
2
4
|
require 'uri'
|
5
|
+
require 'pathname'
|
3
6
|
|
4
7
|
describe Ngzip do
|
5
|
-
|
6
8
|
it 'must support the static method :build' do
|
7
|
-
Ngzip.respond_to?(:build).must_equal true
|
8
|
-
end
|
9
|
-
|
9
|
+
expect(Ngzip.respond_to?(:build)).must_equal true
|
10
|
+
end
|
10
11
|
end
|
11
12
|
|
12
13
|
describe Ngzip::Builder do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
let(:
|
18
|
-
let(:
|
19
|
-
let(:
|
20
|
-
let(:
|
21
|
-
|
14
|
+
def encode_file_path(path)
|
15
|
+
ERB::Util.url_encode path
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:builder) { Ngzip::Builder.new }
|
19
|
+
let(:lorem) { File.expand_path('../../data/a/lorem.txt', __dir__) }
|
20
|
+
let(:ipsum) { File.expand_path('../../data/a/ipsum.txt', __dir__) }
|
21
|
+
let(:without_dot) { File.expand_path('../../data/a/filename-without-a-dot', __dir__) }
|
22
|
+
let(:my_file) { File.expand_path('../../data/a/d/my_file.txt', __dir__) }
|
23
|
+
let(:whitespaced) { File.expand_path('../../data/a/A filename with whitespace.txt', __dir__) }
|
24
|
+
let(:plused) { File.expand_path('../../data/c/A filename with space and + in it.txt', __dir__) }
|
25
|
+
let(:cargo) { File.expand_path('../../data/b/Cargo.png', __dir__) }
|
26
|
+
let(:sit) { File.expand_path('../../data/sit.txt', __dir__) }
|
27
|
+
let(:a) { File.expand_path('../../data/a', __dir__) }
|
28
|
+
let(:questions) { File.expand_path('../../data/c/questions?', __dir__) }
|
29
|
+
|
22
30
|
it 'must be defined' do
|
23
|
-
Ngzip::Builder.wont_be_nil
|
24
|
-
end
|
25
|
-
|
31
|
+
expect(Ngzip::Builder).wont_be_nil
|
32
|
+
end
|
33
|
+
|
26
34
|
it 'must be a class we can call :new on' do
|
27
|
-
Ngzip::Builder.new
|
35
|
+
expect(Ngzip::Builder.new).wont_be_nil
|
28
36
|
end
|
29
|
-
|
37
|
+
|
30
38
|
it 'must respond to :build' do
|
31
|
-
builder.respond_to?(:build).must_equal true
|
39
|
+
expect(builder.respond_to?(:build)).must_equal true
|
32
40
|
end
|
33
|
-
|
34
|
-
describe
|
35
|
-
let(:options) { {:
|
36
|
-
|
41
|
+
|
42
|
+
describe 'with CRC-32 checksums disabled' do
|
43
|
+
let(:options) { { crc: false } }
|
44
|
+
|
37
45
|
it 'must return a correct list for one file' do
|
38
|
-
expected = "- 446 #{lorem} lorem.txt"
|
39
|
-
builder.build(lorem, options).must_equal expected
|
40
|
-
end
|
46
|
+
expected = "- 446 #{encode_file_path(lorem)} lorem.txt"
|
47
|
+
expect(builder.build(lorem, options)).must_equal expected
|
48
|
+
end
|
41
49
|
end
|
42
|
-
|
43
|
-
describe
|
44
|
-
let(:options) { {:
|
45
|
-
|
50
|
+
|
51
|
+
describe 'with CRC-32 checksums enabled' do
|
52
|
+
let(:options) { { crc: true } }
|
53
|
+
|
46
54
|
it 'must return a correct list for one file with a checksum' do
|
47
|
-
expected = "8f92322f 446 #{lorem} lorem.txt"
|
48
|
-
builder.build(lorem, options).must_equal expected
|
55
|
+
expected = "8f92322f 446 #{encode_file_path(lorem)} lorem.txt"
|
56
|
+
expect(builder.build(lorem, options)).must_equal expected
|
49
57
|
end
|
50
|
-
|
58
|
+
|
51
59
|
it 'must return a correct list for one binary file with a checksum' do
|
52
|
-
expected = "b2f4655b 11550 #{cargo} Cargo.png"
|
53
|
-
builder.build(cargo, options).must_equal expected
|
60
|
+
expected = "b2f4655b 11550 #{encode_file_path(cargo)} Cargo.png"
|
61
|
+
expect(builder.build(cargo, options)).must_equal expected
|
54
62
|
end
|
55
|
-
|
63
|
+
|
56
64
|
it 'must escape the path name' do
|
57
|
-
expected = "8f92322f 446 #{
|
58
|
-
builder.build(whitespaced, options).must_equal expected
|
65
|
+
expected = "8f92322f 446 #{encode_file_path(whitespaced)} A filename with whitespace.txt"
|
66
|
+
expect(builder.build(whitespaced, options)).must_equal expected
|
59
67
|
end
|
60
|
-
|
68
|
+
|
61
69
|
it 'must return a correct list for all files in a directory' do
|
62
|
-
expected =
|
63
|
-
expected << "
|
64
|
-
expected << "\n8f92322f 446 #{
|
65
|
-
|
70
|
+
expected = StringIO.new
|
71
|
+
expected << "8f92322f 446 #{encode_file_path(whitespaced)} A filename with whitespace.txt"
|
72
|
+
expected << "\n8f92322f 446 #{encode_file_path(without_dot)} filename-without-a-dot"
|
73
|
+
expected << "\n8f92322f 446 #{encode_file_path(ipsum)} ipsum.txt"
|
74
|
+
expected << "\n8f92322f 446 #{encode_file_path(lorem)} lorem.txt"
|
75
|
+
expected << "\n8f92322f 446 #{encode_file_path(my_file)} d/my_file.txt"
|
76
|
+
expect(builder.build(a, options)).must_equal expected.string
|
66
77
|
end
|
67
|
-
|
78
|
+
|
68
79
|
it 'must allow to mix files and directories' do
|
69
|
-
expected =
|
70
|
-
expected << "
|
71
|
-
expected << "\n8f92322f 446 #{
|
72
|
-
expected << "\
|
73
|
-
|
80
|
+
expected = StringIO.new
|
81
|
+
expected << "8f92322f 446 #{encode_file_path(whitespaced)} a/A filename with whitespace.txt"
|
82
|
+
expected << "\n8f92322f 446 #{encode_file_path(without_dot)} a/filename-without-a-dot"
|
83
|
+
expected << "\n8f92322f 446 #{encode_file_path(ipsum)} a/ipsum.txt"
|
84
|
+
expected << "\n8f92322f 446 #{encode_file_path(lorem)} a/lorem.txt"
|
85
|
+
expected << "\n8f92322f 446 #{encode_file_path(my_file)} a/d/my_file.txt"
|
86
|
+
expected << "\nf7c0867d 1342 #{encode_file_path(sit)} sit.txt"
|
87
|
+
expect(builder.build([a, sit], options)).must_equal expected.string
|
74
88
|
end
|
75
|
-
|
89
|
+
|
76
90
|
it 'must preserve directory names' do
|
77
91
|
expected = [
|
78
|
-
"8f92322f 446 #{lorem} a/lorem.txt",
|
79
|
-
"8f92322f 446 #{ipsum} a/ipsum.txt",
|
80
|
-
"b2f4655b 11550 #{cargo} b/Cargo.png"
|
81
|
-
|
82
|
-
builder.build([lorem,ipsum,cargo], options).must_equal expected
|
92
|
+
"8f92322f 446 #{encode_file_path(lorem)} a/lorem.txt",
|
93
|
+
"8f92322f 446 #{encode_file_path(ipsum)} a/ipsum.txt",
|
94
|
+
"b2f4655b 11550 #{encode_file_path(cargo)} b/Cargo.png"
|
95
|
+
].join("\n")
|
96
|
+
expect(builder.build([lorem, ipsum, cargo], options)).must_equal expected
|
83
97
|
end
|
84
|
-
|
98
|
+
|
85
99
|
it 'must honor the CRC cache' do
|
86
|
-
invalid_but_cached =
|
87
|
-
expected = "#{invalid_but_cached} 446 #{lorem} lorem.txt"
|
88
|
-
builder.build(lorem, options.merge(:
|
100
|
+
invalid_but_cached = '781aaabcc124'
|
101
|
+
expected = "#{invalid_but_cached} 446 #{encode_file_path(lorem)} lorem.txt"
|
102
|
+
expect(builder.build(lorem, options.merge(crc_cache: { lorem => invalid_but_cached }))).must_equal expected
|
89
103
|
end
|
90
|
-
|
104
|
+
|
91
105
|
it 'must remove common directories by default' do
|
92
|
-
pathes = builder.build([lorem, ipsum]).split("\n").map{|line| line.split.last}
|
93
|
-
expected = [
|
94
|
-
pathes.must_equal expected
|
106
|
+
pathes = builder.build([lorem, ipsum]).split("\n").map { |line| line.split.last }
|
107
|
+
expected = ['lorem.txt', 'ipsum.txt']
|
108
|
+
expect(pathes).must_equal expected
|
95
109
|
end
|
96
|
-
|
110
|
+
|
111
|
+
describe 'when building the manifest from a directory path parameter' do
|
112
|
+
it 'removes trailing slash from builder file path' do
|
113
|
+
dir_path = File.join(File.dirname(lorem), '/')
|
114
|
+
result = builder.build(dir_path)
|
115
|
+
encoded_host_path = ERB::Util.url_encode(File.join(File.expand_path('../data', File.dirname(__dir__)), '/'))
|
116
|
+
manifest = <<~MANIFEST.chomp
|
117
|
+
8f92322f 446 #{encoded_host_path}a%2FA%20filename%20with%20whitespace.txt A filename with whitespace.txt
|
118
|
+
8f92322f 446 #{encoded_host_path}a%2Ffilename-without-a-dot filename-without-a-dot
|
119
|
+
8f92322f 446 #{encoded_host_path}a%2Fipsum.txt ipsum.txt
|
120
|
+
8f92322f 446 #{encoded_host_path}a%2Florem.txt lorem.txt
|
121
|
+
8f92322f 446 #{encoded_host_path}a%2Fd%2Fmy_file.txt d/my_file.txt
|
122
|
+
MANIFEST
|
123
|
+
expect(result).must_equal manifest
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
97
127
|
it 'must keep common directories if :base_dir is provided' do
|
98
|
-
options = {:
|
99
|
-
pathes = builder.build([lorem, ipsum], options).split("\n").map{|line| line.split.last}
|
100
|
-
expected = [
|
101
|
-
pathes.must_equal expected
|
128
|
+
options = { base_dir: Pathname.new(lorem).parent.parent.to_s }
|
129
|
+
pathes = builder.build([lorem, ipsum], options).split("\n").map { |line| line.split.last }
|
130
|
+
expected = ['a/lorem.txt', 'a/ipsum.txt']
|
131
|
+
expect(pathes).must_equal expected
|
102
132
|
end
|
103
|
-
|
133
|
+
|
104
134
|
it 'must cope with a trailing / in the :base_dir' do
|
105
|
-
options = {:
|
106
|
-
pathes = builder.build([lorem, ipsum], options).split("\n").map{|line| line.split.last}
|
107
|
-
expected = [
|
108
|
-
pathes.must_equal expected
|
109
|
-
|
135
|
+
options = { base_dir: "#{Pathname.new(lorem).parent.parent}/" }
|
136
|
+
pathes = builder.build([lorem, ipsum], options).split("\n").map { |line| line.split.last }
|
137
|
+
expected = ['a/lorem.txt', 'a/ipsum.txt']
|
138
|
+
expect(pathes).must_equal expected
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'must correctly encode filenames with a "+"' do
|
142
|
+
options = {}
|
143
|
+
name = File.join(Pathname.new(plused).parent.to_s, 'A filename with space and + in it.txt')
|
144
|
+
expected = "8f92322f 446 #{encode_file_path(name)} A filename with space and + in it.txt"
|
145
|
+
expect(builder.build([plused], options)).must_equal expected
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'must correctly encode the "?" character' do
|
149
|
+
name = File.join(Pathname.new(questions).parent.to_s, 'questions?/test.txt')
|
150
|
+
expected = "f03102f5 13 #{encode_file_path(name)} test.txt"
|
151
|
+
expect(builder.build([File.join(questions, 'test.txt')])).must_equal expected
|
110
152
|
end
|
111
|
-
|
112
|
-
|
113
153
|
end
|
114
|
-
|
115
154
|
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative '../../test_helper'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
describe Ngzip do
|
6
|
+
it 'must define a version' do
|
7
|
+
expect(Ngzip::VERSION).wont_be_nil
|
7
8
|
end
|
8
|
-
|
9
|
-
end
|
9
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'minitest/autorun'
|
2
4
|
require 'minitest/pride'
|
3
|
-
require
|
4
|
-
|
5
|
+
require 'minitest/reporters'
|
6
|
+
require 'pry'
|
7
|
+
Minitest::Reporters.use!
|
8
|
+
require File.expand_path('../lib/ngzip.rb', __dir__)
|
metadata
CHANGED
@@ -1,58 +1,67 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ngzip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- dup2
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2020-11-25 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '1.3'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '1.3'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
|
-
|
47
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |-
|
56
|
+
Provides a nginx mod_zip compatible file manifest for streaming support.
|
57
|
+
See http://wiki.nginx.org/NginxNgxZip for the nginx module.
|
48
58
|
email:
|
49
|
-
- zarkov@
|
59
|
+
- zarkov@cargoserver.ch
|
50
60
|
executables: []
|
51
61
|
extensions: []
|
52
62
|
extra_rdoc_files: []
|
53
63
|
files:
|
54
|
-
- .gitignore
|
55
|
-
- .rvmrc
|
64
|
+
- ".gitignore"
|
56
65
|
- CHANGELOG.md
|
57
66
|
- Gemfile
|
58
67
|
- LICENSE.txt
|
@@ -63,10 +72,14 @@ files:
|
|
63
72
|
- lib/ngzip/version.rb
|
64
73
|
- ngzip.gemspec
|
65
74
|
- test/data/a/A filename with whitespace.txt
|
75
|
+
- test/data/a/d/my_file.txt
|
76
|
+
- test/data/a/filename-without-a-dot
|
66
77
|
- test/data/a/ipsum.txt
|
67
78
|
- test/data/a/lorem.txt
|
68
79
|
- test/data/b/Cargo.png
|
69
80
|
- test/data/b/dolor.txt
|
81
|
+
- test/data/c/A filename with space and + in it.txt
|
82
|
+
- test/data/c/questions?/test.txt
|
70
83
|
- test/data/sit.txt
|
71
84
|
- test/lib/ngzip/builder_test.rb
|
72
85
|
- test/lib/ngzip/version_test.rb
|
@@ -74,40 +87,36 @@ files:
|
|
74
87
|
homepage: https://github.com/cargoserver/ngzip
|
75
88
|
licenses:
|
76
89
|
- MIT
|
77
|
-
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
78
92
|
rdoc_options: []
|
79
93
|
require_paths:
|
80
94
|
- lib
|
81
95
|
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
96
|
requirements:
|
84
|
-
- -
|
97
|
+
- - ">="
|
85
98
|
- !ruby/object:Gem::Version
|
86
99
|
version: '0'
|
87
|
-
segments:
|
88
|
-
- 0
|
89
|
-
hash: 4140413543763942870
|
90
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
-
none: false
|
92
101
|
requirements:
|
93
|
-
- -
|
102
|
+
- - ">="
|
94
103
|
- !ruby/object:Gem::Version
|
95
104
|
version: '0'
|
96
|
-
segments:
|
97
|
-
- 0
|
98
|
-
hash: 4140413543763942870
|
99
105
|
requirements: []
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
specification_version: 3
|
106
|
+
rubygems_version: 3.0.8
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
104
109
|
summary: Provides a nginx mod_zip compatible file manifest for streaming support
|
105
110
|
test_files:
|
106
111
|
- test/data/a/A filename with whitespace.txt
|
112
|
+
- test/data/a/d/my_file.txt
|
113
|
+
- test/data/a/filename-without-a-dot
|
107
114
|
- test/data/a/ipsum.txt
|
108
115
|
- test/data/a/lorem.txt
|
109
116
|
- test/data/b/Cargo.png
|
110
117
|
- test/data/b/dolor.txt
|
118
|
+
- test/data/c/A filename with space and + in it.txt
|
119
|
+
- test/data/c/questions?/test.txt
|
111
120
|
- test/data/sit.txt
|
112
121
|
- test/lib/ngzip/builder_test.rb
|
113
122
|
- test/lib/ngzip/version_test.rb
|
data/.rvmrc
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
-
# development environment upon cd'ing into the directory
|
5
|
-
|
6
|
-
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
7
|
-
# Only full ruby name is supported here, for short names use:
|
8
|
-
# echo "rvm use 1.9.3" > .rvmrc
|
9
|
-
environment_id="ruby-1.9.3-p392@ngzip"
|
10
|
-
|
11
|
-
# Uncomment the following lines if you want to verify rvm version per project
|
12
|
-
# rvmrc_rvm_version="1.18.14 (version)" # 1.10.1 seams as a safe start
|
13
|
-
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
14
|
-
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
15
|
-
# return 1
|
16
|
-
# }
|
17
|
-
|
18
|
-
# First we attempt to load the desired environment directly from the environment
|
19
|
-
# file. This is very fast and efficient compared to running through the entire
|
20
|
-
# CLI and selector. If you want feedback on which environment was used then
|
21
|
-
# insert the word 'use' after --create as this triggers verbose mode.
|
22
|
-
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
23
|
-
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
24
|
-
then
|
25
|
-
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
26
|
-
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
27
|
-
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
28
|
-
else
|
29
|
-
# If the environment file has not yet been created, use the RVM CLI to select.
|
30
|
-
rvm --create "$environment_id" || {
|
31
|
-
echo "Failed to create RVM environment '${environment_id}'."
|
32
|
-
return 1
|
33
|
-
}
|
34
|
-
fi
|
35
|
-
|
36
|
-
# If you use bundler, this might be useful to you:
|
37
|
-
# if [[ -s Gemfile ]] && {
|
38
|
-
# ! builtin command -v bundle >/dev/null ||
|
39
|
-
# builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
|
40
|
-
# }
|
41
|
-
# then
|
42
|
-
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
|
43
|
-
# gem install bundler
|
44
|
-
# fi
|
45
|
-
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
|
46
|
-
# then
|
47
|
-
# bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
|
48
|
-
# fi
|