ngzip 1.0.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 456fae1b62d713966116eba3fc4a54ed579722faee0eb6c70f10559ed9777417
4
+ data.tar.gz: 77b9dc4077689d672b732025c41e913e6b6326c4659a7eeaa36c190a6d7d2089
5
+ SHA512:
6
+ metadata.gz: '09275f7ae55b7c94af391eb829f6810016093a57ae550cad93f82f9f5e7c2ca99eea7e9781bc9f895ca97a22ffa39e845fac6449b196768bd502b3f36a88069b'
7
+ data.tar.gz: 6f0fcb9a9daf07ac7de34d468591bdb1920644eb8c2691b4b63a100ce59f0cf5005c7569f51d99bd47d9d6f0c256f2326e27a40d944e63b36e95cdb24ef8a2db
@@ -0,0 +1,16 @@
1
+ env:
2
+ RUBY_VERSION: 2.6.6
3
+ name: Rspec tests
4
+ on: [push,pull_request]
5
+ jobs:
6
+ rspec-tests:
7
+ name: RSpec
8
+ runs-on: ubuntu-18.04
9
+ steps:
10
+ - uses: actions/checkout@v1
11
+ - uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: ${{ env.RUBY_VERSION }}
14
+ bundler-cache: true
15
+ - name: Run tests
16
+ run: bundler exec rake
data/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ ### 1.2.0 (2021-07-08)
2
+
3
+ * Fixed an issue with brackets in file names (thanks to @mecampbellsoup)
4
+ * Code cleanup
5
+ * Fixed dependencies
6
+ * Activated github CI actions
7
+
8
+ ### 1.1.0 (2020-11-25)
9
+
10
+ * Exclude file name from detect common prefix (thanks to @mecampbellsoup)
11
+ * Code cleanup
12
+
13
+ ### 1.0.7 (2017-10-20)
14
+
15
+ * Fixed an issue with '?' encoding
16
+
17
+ ### 1.0.6 (2013-12-12)
18
+
19
+ * Fixed a regression from 1.0.5 where directories were included due to the changed pattern
20
+
21
+ ### 1.0.5 (2013-12-12)
22
+
23
+ * Fixed issue #2 (files without extensions being ignored)
24
+
1
25
  ### 1.0.4 (2013-09-20)
2
26
 
3
27
  * Fixed issue #1 ("+" character in filename)
@@ -17,4 +41,3 @@
17
41
  ### 1.0.0 (2013-07-14)
18
42
 
19
43
  * Initial public release
20
-
data/Gemfile CHANGED
@@ -1,4 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in ngzip.gemspec
6
+ group :test do
7
+ gem 'minitest'
8
+ gem 'minitest-reporters'
9
+ gem 'pry'
10
+ end
11
+
4
12
  gemspec
data/LICENSE.txt CHANGED
@@ -1,4 +1,5 @@
1
1
  Copyright (c) 2013 ncode gmbh
2
+ Copyright (c) 2017 CargoServer AG
2
3
 
3
4
  MIT License
4
5
 
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 = Nginx::Builder.new()
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,7 @@ 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.
71
+ Copyright (c) 2021, Swiss Cyber Gate AG. All Rights Reserved.
70
72
 
71
73
  This project is licenced under the [MIT License](LICENSE.txt).
72
-
data/Rakefile CHANGED
@@ -1,11 +1,13 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
2
 
3
- require "rake/testtask"
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 :default => :test
12
+
13
+ task default: :test
data/lib/ngzip.rb CHANGED
@@ -1,8 +1,11 @@
1
- require "ngzip/version"
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().build(files, options)
9
+ Ngzip::Builder.new.build(files, options)
7
10
  end
8
11
  end
data/lib/ngzip/builder.rb CHANGED
@@ -1,113 +1,119 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'zlib'
2
4
  require 'uri'
5
+ require 'erb'
6
+ require 'refinements'
7
+
8
+ using Refinements
3
9
 
4
10
  module Ngzip
5
-
11
+ # The manifest builder based on the file list
6
12
  class Builder
7
-
8
13
  BUFFER_SIZE = 8 * 1024
9
-
14
+
10
15
  # Public: Build the files manifest for mod_zip, see http://wiki.nginx.org/NginxNgxZip for the specs.
11
- #
16
+ #
12
17
  # files - An Array of absolute file path elements
13
18
  # options - The options, see below
14
- #
19
+ #
15
20
  # Returns a line for each file separated by \n
16
- #
21
+ #
17
22
  # The following options are available:
18
- # :crc => Enable or disable CRC-32 checksums
19
- # :crc_cache => Allows for provided cached CRC-32 checksums in a hash where the key is the file path
20
- # :base_dir => Use this as root for the relative pathes in the archive, keep all directories below
23
+ # crc: Enable or disable CRC-32 checksums
24
+ # crc_cache: Allows for provided cached CRC-32 checksums in a hash where the key is the file path
25
+ # base_dir: Use this as root for the relative pathes in the archive, keep all directories below
21
26
  def build(files, options = {})
22
- settings = {:crc => true}
27
+ settings = { crc: true }
23
28
  settings.merge! options
24
-
29
+
25
30
  list = file_list(files)
26
31
  prefix = options[:base_dir] || detect_common_prefix(list)
27
32
  prefix += '/' unless prefix.end_with?('/')
28
33
  list.map do |f|
29
- sprintf('%s %d %s %s',
30
- compute_crc32(f, settings),
31
- File.size(f).to_i,
32
- Builder.encode(f),
33
- f.gsub(prefix, '')
34
+ format(
35
+ '%<crc>s %<size>d %<url>s %<name>s',
36
+ {
37
+ crc: compute_crc32(f, settings),
38
+ size: File.size(f).to_i,
39
+ url: Builder.encode(f),
40
+ name: f.gsub(prefix, '')
41
+ }
34
42
  )
35
43
  end.join("\n")
36
44
  end
37
45
 
38
46
  # Public: Get the special header to signal the mod_zip
39
- #
47
+ #
40
48
  # Returns the header as a string "key: value"
41
- def header()
42
- "X-Archive-Files: zip"
49
+ def header
50
+ 'X-Archive-Files: zip'
43
51
  end
44
-
45
-
46
- # Public: Encode the string
52
+
53
+ # Public: Encode the string
47
54
  #
48
55
  # Returns the encoded string using URL escape formatting
49
56
  def self.encode(string)
50
- URI.encode(string).sub('+', "%2B")
57
+ ERB::Util.url_encode(string)
51
58
  end
52
-
59
+
53
60
  private
54
-
61
+
55
62
  # Internal: Compute a common prefix from a list of path elements
56
- #
63
+ #
57
64
  # list - The list of file path elements
58
- #
65
+ #
59
66
  # Returns a common prefix
60
67
  def detect_common_prefix(list)
61
- if list.size == 1
62
- return File.dirname(list.first)
63
- end
64
- prefix = ''
65
- min, max = list.sort.values_at(0, -1)
68
+ return File.dirname(list.first) if list.size == 1
69
+
70
+ prefix = StringIO.new
71
+ excluding_file_names = list.map { |p| File.dirname p }
72
+ min, max = excluding_file_names.sort.values_at(0, -1)
66
73
  min.split(//).each_with_index do |c, i|
67
74
  break if c != max[i, 1]
75
+
68
76
  prefix << c
69
77
  end
70
- prefix
78
+ prefix.string
71
79
  end
72
-
80
+
73
81
  # Internal: Compute the file list by expanding directories
74
- #
82
+ #
75
83
  def file_list(files)
76
84
  Array(files).map do |e|
77
85
  if File.directory?(e)
78
- Dir.glob("#{e}/**/*.*")
86
+ # `expand_path` removes any trailing slash from the path string
87
+ # `String#escape_glob` handles bracket literals otherwise interpreted as glob control characters
88
+ sanitized_path = File.expand_path(e.escape_glob)
89
+ Dir.glob("#{sanitized_path}/**/*").reject { |f| File.directory?(f) }
79
90
  else
80
91
  e
81
92
  end
82
93
  end.flatten
83
94
  end
84
-
85
-
86
- # Internal: Compute the CRC-32 checksum for a file unless the settings
87
- # disable the computation (:crc => false) and this method returns "-"
88
- #
95
+
96
+ # Internal: Compute the CRC-32 checksum for a file unless the settings
97
+ # disable the computation (crc: false) and this method returns "-"
98
+ #
89
99
  # file - The full path to the file
90
100
  # settings - The settings hash
91
- #
101
+ #
92
102
  # Returns a hex string
93
103
  def compute_crc32(file, settings)
94
104
  return '-' unless settings[:crc]
95
-
105
+
96
106
  # honor the cache
97
- if settings[:crc_cache] && settings[:crc_cache][file]
98
- return settings[:crc_cache][file]
99
- end
100
-
107
+ return settings[:crc_cache][file] if settings[:crc_cache] && settings[:crc_cache][file]
108
+
101
109
  # read using a buffer, we might operate on large files!
102
110
  crc32 = 0
103
- File.open(file,'rb') do |f|
104
- while buffer = f.read(BUFFER_SIZE) do
105
- crc32 = Zlib.crc32(buffer, crc32)
111
+ File.open(file, 'rb') do |f|
112
+ while (buffer = f.read(BUFFER_SIZE))
113
+ crc32 = Zlib.crc32(buffer, crc32)
106
114
  end
107
115
  end
108
116
  crc32.to_s(16)
109
117
  end
110
-
111
118
  end
112
-
113
- end
119
+ end
data/lib/ngzip/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ngzip
2
- VERSION = "1.0.4"
4
+ VERSION = '1.2.0'
3
5
  end
@@ -0,0 +1,9 @@
1
+ module Refinements
2
+ refine String do
3
+ # Ref: https://stackoverflow.com/questions/14127343/why-dir-glob-in-ruby-doesnt-see-files-in-folders-named-with-square-brackets
4
+ # Ref: https://bugs.ruby-lang.org/issues/8258
5
+ def escape_glob
6
+ self.gsub(/[\\\{\}\[\]\*\?]/) { |x| "\\" + x }
7
+ end
8
+ end
9
+ end
data/ngzip.gemspec CHANGED
@@ -1,24 +1,28 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
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 = "ngzip"
9
+ spec.name = 'ngzip'
8
10
  spec.version = Ngzip::VERSION
9
- spec.authors = ["dup2"]
10
- spec.email = ["zarkov@ncode.ch"]
11
- spec.description = %q{Provides a nginx mod_zip compatible file manifest for streaming support.
12
- See http://wiki.nginx.org/NginxNgxZip for the nginx module.}
13
- spec.summary = %q{Provides a nginx mod_zip compatible file manifest for streaming support}
14
- spec.homepage = "https://github.com/cargoserver/ngzip"
15
- spec.license = "MIT"
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 = ["lib"]
22
+ spec.require_paths = ['lib']
23
+ spec.required_ruby_version = '>= 2.3'
21
24
 
22
- spec.add_development_dependency "bundler", "~> 1.3"
23
- spec.add_development_dependency "rake"
25
+ spec.add_development_dependency 'bundler', '>= 2.2.10'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'rubocop'
24
28
  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,3 @@
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.
2
+
3
+ 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,122 +1,168 @@
1
- require_relative "../../test_helper"
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
- let(:builder) {Ngzip::Builder.new()}
15
- let(:lorem) {File.expand_path('../../../data/a/lorem.txt', __FILE__)}
16
- let(:ipsum) {File.expand_path('../../../data/a/ipsum.txt', __FILE__)}
17
- let(:whitespaced) {File.expand_path('../../../data/a/A filename with whitespace.txt', __FILE__)}
18
- let(:plused) {File.expand_path('../../../data/c/A filename with space and + in it.txt', __FILE__)}
19
- let(:cargo) {File.expand_path('../../../data/b/Cargo.png', __FILE__)}
20
- let(:sit) {File.expand_path('../../../data/sit.txt', __FILE__)}
21
- let(:a) {File.expand_path('../../../data/a', __FILE__)}
22
-
14
+ def encode_file_path(path)
15
+ ERB::Util.url_encode path
16
+ end
17
+
18
+ let(:builder) { Ngzip::Builder.new }
19
+ let(:sit) { File.expand_path('../../data/sit.txt', __dir__) }
20
+ let(:lorem) { File.expand_path('../../data/a/lorem.txt', __dir__) }
21
+ let(:ipsum) { File.expand_path('../../data/a/ipsum.txt', __dir__) }
22
+ let(:my_file) { File.expand_path('../../data/a/d/my_file.txt', __dir__) }
23
+ let(:without_dot) { File.expand_path('../../data/a/filename-without-a-dot', __dir__) }
24
+ let(:whitespaced) { File.expand_path('../../data/a/A filename with whitespace.txt', __dir__) }
25
+ let(:a) { File.expand_path('../../data/a', __dir__) }
26
+ let(:cargo) { File.expand_path('../../data/b/Cargo.png', __dir__) }
27
+ let(:plused) { File.expand_path('../../data/c/A filename with space and + in it.txt', __dir__) }
28
+ let(:questions) { File.expand_path('../../data/c/questions?', __dir__) }
29
+ let(:brackets) { File.expand_path('../../data/c/[brackets]', __dir__) }
30
+
23
31
  it 'must be defined' do
24
- Ngzip::Builder.wont_be_nil
25
- end
26
-
32
+ expect(Ngzip::Builder).wont_be_nil
33
+ end
34
+
27
35
  it 'must be a class we can call :new on' do
28
- Ngzip::Builder.new().wont_be_nil
36
+ expect(Ngzip::Builder.new).wont_be_nil
29
37
  end
30
-
38
+
31
39
  it 'must respond to :build' do
32
- builder.respond_to?(:build).must_equal true
40
+ expect(builder.respond_to?(:build)).must_equal true
33
41
  end
34
-
35
- describe "with CRC-32 checksums disabled" do
36
- let(:options) { {:crc => false}}
37
-
42
+
43
+ describe 'with CRC-32 checksums disabled' do
44
+ let(:options) { { crc: false } }
45
+
38
46
  it 'must return a correct list for one file' do
39
- expected = "- 446 #{lorem} lorem.txt"
40
- builder.build(lorem, options).must_equal expected
41
- end
47
+ expected = "- 446 #{encode_file_path(lorem)} lorem.txt"
48
+ expect(builder.build(lorem, options)).must_equal expected
49
+ end
42
50
  end
43
-
44
- describe "with CRC-32 checksums enabled" do
45
- let(:options) { {:crc => true}}
46
-
51
+
52
+ describe 'with CRC-32 checksums enabled' do
53
+ let(:options) { { crc: true } }
54
+
47
55
  it 'must return a correct list for one file with a checksum' do
48
- expected = "8f92322f 446 #{lorem} lorem.txt"
49
- builder.build(lorem, options).must_equal expected
56
+ expected = "8f92322f 446 #{encode_file_path(lorem)} lorem.txt"
57
+ expect(builder.build(lorem, options)).must_equal expected
50
58
  end
51
-
59
+
52
60
  it 'must return a correct list for one binary file with a checksum' do
53
- expected = "b2f4655b 11550 #{cargo} Cargo.png"
54
- builder.build(cargo, options).must_equal expected
61
+ expected = "b2f4655b 11550 #{encode_file_path(cargo)} Cargo.png"
62
+ expect(builder.build(cargo, options)).must_equal expected
55
63
  end
56
-
64
+
57
65
  it 'must escape the path name' do
58
- expected = "8f92322f 446 #{URI.escape(whitespaced)} A filename with whitespace.txt"
59
- builder.build(whitespaced, options).must_equal expected
66
+ expected = "8f92322f 446 #{encode_file_path(whitespaced)} A filename with whitespace.txt"
67
+ expect(builder.build(whitespaced, options)).must_equal expected
60
68
  end
61
-
69
+
62
70
  it 'must return a correct list for all files in a directory' do
63
- expected = "8f92322f 446 #{URI.escape(whitespaced)} A filename with whitespace.txt"
64
- expected << "\n8f92322f 446 #{ipsum} ipsum.txt"
65
- expected << "\n8f92322f 446 #{lorem} lorem.txt"
66
- builder.build(a,options).must_equal expected
71
+ expected = <<~MANIFEST.chomp
72
+ 8f92322f 446 #{encode_file_path(whitespaced)} A filename with whitespace.txt
73
+ 8f92322f 446 #{encode_file_path(without_dot)} filename-without-a-dot
74
+ 8f92322f 446 #{encode_file_path(ipsum)} ipsum.txt
75
+ 8f92322f 446 #{encode_file_path(lorem)} lorem.txt
76
+ 8f92322f 446 #{encode_file_path(my_file)} d/my_file.txt
77
+ MANIFEST
78
+ expect(builder.build(a, options).lines.sort.map(&:chomp)).must_equal expected.lines.sort.map(&:chomp)
67
79
  end
68
-
80
+
69
81
  it 'must allow to mix files and directories' do
70
- expected = "8f92322f 446 #{URI.escape(whitespaced)} a/A filename with whitespace.txt"
71
- expected << "\n8f92322f 446 #{ipsum} a/ipsum.txt"
72
- expected << "\n8f92322f 446 #{lorem} a/lorem.txt"
73
- expected << "\nf7c0867d 1342 #{sit} sit.txt"
74
- builder.build([a,sit], options).must_equal expected
82
+ expected = <<~MANIFEST.chomp
83
+ 8f92322f 446 #{encode_file_path(whitespaced)} a/A filename with whitespace.txt
84
+ 8f92322f 446 #{encode_file_path(without_dot)} a/filename-without-a-dot
85
+ 8f92322f 446 #{encode_file_path(ipsum)} a/ipsum.txt
86
+ 8f92322f 446 #{encode_file_path(lorem)} a/lorem.txt
87
+ 8f92322f 446 #{encode_file_path(my_file)} a/d/my_file.txt
88
+ f7c0867d 1342 #{encode_file_path(sit)} sit.txt
89
+ MANIFEST
90
+ expect(builder.build([a, sit], options).lines.sort.map(&:chomp)).must_equal expected.lines.sort.map(&:chomp)
75
91
  end
76
-
92
+
77
93
  it 'must preserve directory names' do
78
94
  expected = [
79
- "8f92322f 446 #{lorem} a/lorem.txt",
80
- "8f92322f 446 #{ipsum} a/ipsum.txt",
81
- "b2f4655b 11550 #{cargo} b/Cargo.png"
82
- ].join("\n")
83
- builder.build([lorem,ipsum,cargo], options).must_equal expected
95
+ "8f92322f 446 #{encode_file_path(lorem)} a/lorem.txt",
96
+ "8f92322f 446 #{encode_file_path(ipsum)} a/ipsum.txt",
97
+ "b2f4655b 11550 #{encode_file_path(cargo)} b/Cargo.png"
98
+ ].join("\n")
99
+ expect(builder.build([lorem, ipsum, cargo], options)).must_equal expected
84
100
  end
85
-
101
+
86
102
  it 'must honor the CRC cache' do
87
- invalid_but_cached = "781aaabcc124"
88
- expected = "#{invalid_but_cached} 446 #{lorem} lorem.txt"
89
- builder.build(lorem, options.merge(:crc_cache => {lorem => invalid_but_cached})).must_equal expected
103
+ invalid_but_cached = '781aaabcc124'
104
+ expected = "#{invalid_but_cached} 446 #{encode_file_path(lorem)} lorem.txt"
105
+ expect(builder.build(lorem, options.merge(crc_cache: { lorem => invalid_but_cached }))).must_equal expected
90
106
  end
91
-
107
+
92
108
  it 'must remove common directories by default' do
93
- pathes = builder.build([lorem, ipsum]).split("\n").map{|line| line.split.last}
94
- expected = ["lorem.txt", "ipsum.txt"]
95
- pathes.must_equal expected
109
+ pathes = builder.build([lorem, ipsum]).split("\n").map { |line| line.split.last }
110
+ expected = ['lorem.txt', 'ipsum.txt']
111
+ expect(pathes).must_equal expected
96
112
  end
97
-
113
+
114
+ describe 'when building the manifest from a directory path parameter' do
115
+ describe 'the path includes brackets' do
116
+ it 'handles special characters in file names' do
117
+ result = builder.build(brackets)
118
+ encoded_host_path = ERB::Util.url_encode(File.join(File.expand_path('../data', File.dirname(__dir__)), '/'))
119
+ manifest = <<~MANIFEST.chomp
120
+ dee5e05b 894 #{encoded_host_path}c%2F%5Bbrackets%5D%2F%28parenthesis%29.txt (parenthesis).txt
121
+ MANIFEST
122
+ expect(result).must_equal manifest
123
+ end
124
+ end
125
+
126
+ it 'removes trailing slash from builder file path' do
127
+ dir_path = File.join(File.dirname(lorem), '/')
128
+ result = builder.build(dir_path)
129
+ encoded_host_path = ERB::Util.url_encode(File.join(File.expand_path('../data', File.dirname(__dir__)), '/'))
130
+ manifest = <<~MANIFEST.chomp
131
+ 8f92322f 446 #{encoded_host_path}a%2FA%20filename%20with%20whitespace.txt A filename with whitespace.txt
132
+ 8f92322f 446 #{encoded_host_path}a%2Ffilename-without-a-dot filename-without-a-dot
133
+ 8f92322f 446 #{encoded_host_path}a%2Fipsum.txt ipsum.txt
134
+ 8f92322f 446 #{encoded_host_path}a%2Florem.txt lorem.txt
135
+ 8f92322f 446 #{encoded_host_path}a%2Fd%2Fmy_file.txt d/my_file.txt
136
+ MANIFEST
137
+ expect(result.lines.sort.map(&:chomp)).must_equal manifest.lines.sort.map(&:chomp)
138
+ end
139
+ end
140
+
98
141
  it 'must keep common directories if :base_dir is provided' do
99
- options = {:base_dir => Pathname.new(lorem).parent.parent.to_s}
100
- pathes = builder.build([lorem, ipsum], options).split("\n").map{|line| line.split.last}
101
- expected = ["a/lorem.txt", "a/ipsum.txt"]
102
- pathes.must_equal expected
142
+ options = { base_dir: Pathname.new(lorem).parent.parent.to_s }
143
+ pathes = builder.build([lorem, ipsum], options).split("\n").map { |line| line.split.last }
144
+ expected = ['a/lorem.txt', 'a/ipsum.txt']
145
+ expect(pathes).must_equal expected
103
146
  end
104
-
147
+
105
148
  it 'must cope with a trailing / in the :base_dir' do
106
- options = {:base_dir => Pathname.new(lorem).parent.parent.to_s + '/'}
107
- pathes = builder.build([lorem, ipsum], options).split("\n").map{|line| line.split.last}
108
- expected = ["a/lorem.txt", "a/ipsum.txt"]
109
- pathes.must_equal expected
149
+ options = { base_dir: "#{Pathname.new(lorem).parent.parent}/" }
150
+ pathes = builder.build([lorem, ipsum], options).split("\n").map { |line| line.split.last }
151
+ expected = ['a/lorem.txt', 'a/ipsum.txt']
152
+ expect(pathes).must_equal expected
110
153
  end
111
-
154
+
112
155
  it 'must correctly encode filenames with a "+"' do
113
156
  options = {}
114
- name = File.join(Pathname.new(plused).parent.to_s, 'A%20filename%20with%20space%20and%20%2B%20in%20it.txt')
115
- expected = "8f92322f 446 #{name} A filename with space and + in it.txt"
116
- builder.build([plused], options).must_equal expected
157
+ name = File.join(Pathname.new(plused).parent.to_s, 'A filename with space and + in it.txt')
158
+ expected = "8f92322f 446 #{encode_file_path(name)} A filename with space and + in it.txt"
159
+ expect(builder.build([plused], options)).must_equal expected
160
+ end
161
+
162
+ it 'must correctly encode the "?" character' do
163
+ name = File.join(Pathname.new(questions).parent.to_s, 'questions?/test.txt')
164
+ expected = "f03102f5 13 #{encode_file_path(name)} test.txt"
165
+ expect(builder.build([File.join(questions, 'test.txt')])).must_equal expected
117
166
  end
118
-
119
-
120
167
  end
121
-
122
168
  end
@@ -1,9 +1,9 @@
1
- require_relative "../../test_helper"
1
+ # frozen_string_literal: true
2
2
 
3
- describe Ngzip do
3
+ require_relative '../../test_helper'
4
4
 
5
- it "must define a version" do
6
- Ngzip::VERSION.wont_be_nil
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 File.expand_path('../../lib/ngzip.rb', __FILE__)
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,68 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ngzip
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
5
- prerelease:
4
+ version: 1.2.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: 2013-09-20 00:00:00.000000000 Z
11
+ date: 2021-07-08 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
- version: '1.3'
19
+ version: 2.2.10
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
- version: '1.3'
26
+ version: 2.2.10
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
- description: ! "Provides a nginx mod_zip compatible file manifest for streaming support.\n
47
- \ See http://wiki.nginx.org/NginxNgxZip for the nginx module."
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@ncode.ch
59
+ - zarkov@cargoserver.ch
50
60
  executables: []
51
61
  extensions: []
52
62
  extra_rdoc_files: []
53
63
  files:
54
- - .gitignore
55
- - .rvmrc
64
+ - ".github/workflows/rspec.yaml"
65
+ - ".gitignore"
56
66
  - CHANGELOG.md
57
67
  - Gemfile
58
68
  - LICENSE.txt
@@ -61,13 +71,18 @@ files:
61
71
  - lib/ngzip.rb
62
72
  - lib/ngzip/builder.rb
63
73
  - lib/ngzip/version.rb
74
+ - lib/refinements.rb
64
75
  - ngzip.gemspec
65
76
  - test/data/a/A filename with whitespace.txt
77
+ - test/data/a/d/my_file.txt
78
+ - test/data/a/filename-without-a-dot
66
79
  - test/data/a/ipsum.txt
67
80
  - test/data/a/lorem.txt
68
81
  - test/data/b/Cargo.png
69
82
  - test/data/b/dolor.txt
70
83
  - test/data/c/A filename with space and + in it.txt
84
+ - test/data/c/[brackets]/(parenthesis).txt
85
+ - test/data/c/questions?/test.txt
71
86
  - test/data/sit.txt
72
87
  - test/lib/ngzip/builder_test.rb
73
88
  - test/lib/ngzip/version_test.rb
@@ -75,41 +90,37 @@ files:
75
90
  homepage: https://github.com/cargoserver/ngzip
76
91
  licenses:
77
92
  - MIT
78
- post_install_message:
93
+ metadata: {}
94
+ post_install_message:
79
95
  rdoc_options: []
80
96
  require_paths:
81
97
  - lib
82
98
  required_ruby_version: !ruby/object:Gem::Requirement
83
- none: false
84
99
  requirements:
85
- - - ! '>='
100
+ - - ">="
86
101
  - !ruby/object:Gem::Version
87
- version: '0'
88
- segments:
89
- - 0
90
- hash: 870021569406491909
102
+ version: '2.3'
91
103
  required_rubygems_version: !ruby/object:Gem::Requirement
92
- none: false
93
104
  requirements:
94
- - - ! '>='
105
+ - - ">="
95
106
  - !ruby/object:Gem::Version
96
107
  version: '0'
97
- segments:
98
- - 0
99
- hash: 870021569406491909
100
108
  requirements: []
101
- rubyforge_project:
102
- rubygems_version: 1.8.25
103
- signing_key:
104
- specification_version: 3
109
+ rubygems_version: 3.0.8
110
+ signing_key:
111
+ specification_version: 4
105
112
  summary: Provides a nginx mod_zip compatible file manifest for streaming support
106
113
  test_files:
107
114
  - test/data/a/A filename with whitespace.txt
115
+ - test/data/a/d/my_file.txt
116
+ - test/data/a/filename-without-a-dot
108
117
  - test/data/a/ipsum.txt
109
118
  - test/data/a/lorem.txt
110
119
  - test/data/b/Cargo.png
111
120
  - test/data/b/dolor.txt
112
121
  - test/data/c/A filename with space and + in it.txt
122
+ - test/data/c/[brackets]/(parenthesis).txt
123
+ - test/data/c/questions?/test.txt
113
124
  - test/data/sit.txt
114
125
  - test/lib/ngzip/builder_test.rb
115
126
  - 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