paquette 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/LICENSE.md +10 -0
- data/README.md +90 -0
- data/lib/paquette/gem_server/directory_gem_repository.rb +154 -0
- data/lib/paquette/gem_server/gem_repacker.rb +170 -0
- data/lib/paquette/gem_server/gem_repository.rb +53 -0
- data/lib/paquette/gem_server/personalizer.rb +66 -0
- data/lib/paquette/gem_server/read_gated_repository.rb +74 -0
- data/lib/paquette/gem_server.rb +393 -0
- data/lib/paquette/npm_repacker.rb +153 -0
- data/lib/paquette/npm_server/directory_npm_repository.rb +127 -0
- data/lib/paquette/npm_server/gated_npm_repository.rb +66 -0
- data/lib/paquette/npm_server/npm_repository.rb +53 -0
- data/lib/paquette/npm_server.rb +98 -0
- data/lib/paquette/routes.rb +78 -0
- data/lib/paquette/subdomain_router.rb +59 -0
- data/lib/paquette/version.rb +3 -0
- data/lib/paquette.rb +12 -0
- data/test/fixtures/gems/minuscule_test/minuscule_test-0.1.0.gem +0 -0
- data/test/fixtures/gems/zip_kit/zip_kit-6.2.0.gem +0 -0
- data/test/fixtures/gems/zip_kit/zip_kit-6.2.1.gem +0 -0
- data/test/fixtures/npm/react-dropzone/react-dropzone-14.3.8.tgz +0 -0
- data/test/gem_server/bundler_install_test.rb +86 -0
- data/test/gem_server/directory_gem_repository_test.rb +208 -0
- data/test/gem_server/gem_repacker_test.rb +289 -0
- data/test/gem_server/personalizer_metadata_test.rb +49 -0
- data/test/gem_server/personalizer_test.rb +66 -0
- data/test/gem_server/read_gated_repository_test.rb +254 -0
- data/test/gem_server/repository_stack_test.rb +71 -0
- data/test/gem_server_test.rb +339 -0
- data/test/npm_repacker_sourcemap_test.rb +108 -0
- data/test/npm_repacker_test.rb +117 -0
- data/test/npm_server_test.rb +140 -0
- data/test/routes_test.rb +142 -0
- data/test/subdomain_router_integration_test.rb +126 -0
- data/test/subdomain_router_test.rb +125 -0
- data/test/test_helper.rb +12 -0
- metadata +117 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
require_relative "../test_helper"
|
|
2
|
+
require "open3"
|
|
3
|
+
|
|
4
|
+
class GemRepackerTest < Minitest::Test
|
|
5
|
+
def setup
|
|
6
|
+
@test_gem_path = File.join(FIXTURE_GEMS_DIR, "minuscule_test", "minuscule_test-0.1.0.gem")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_repack_with_line_transformation
|
|
10
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
11
|
+
|
|
12
|
+
# Generate random characters for the replacement
|
|
13
|
+
random_chars = (0...8).map { ("a".."z").to_a[rand(26)] }.join
|
|
14
|
+
|
|
15
|
+
# Use magic comment replacements to replace '# paquette_license_info' with '# LIC#{random_chars}'
|
|
16
|
+
new_gem_path = Paquette::GemServer::GemRepacker.repack(@test_gem_path,
|
|
17
|
+
gemspec_extras: {},
|
|
18
|
+
magic_comment_replacements: {"# paquette_license_info" => "LIC#{random_chars}"})
|
|
19
|
+
|
|
20
|
+
assert File.exist?(new_gem_path)
|
|
21
|
+
assert new_gem_path.end_with?("-repacked.gem")
|
|
22
|
+
|
|
23
|
+
# Unpack the produced gem and verify the replacement
|
|
24
|
+
verify_repacking(new_gem_path, random_chars)
|
|
25
|
+
|
|
26
|
+
# Clean up
|
|
27
|
+
File.delete(new_gem_path) if File.exist?(new_gem_path)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_repack_with_metadata_keys
|
|
31
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
32
|
+
|
|
33
|
+
# Test adding metadata keys to the gemspec
|
|
34
|
+
additional_metadata = {
|
|
35
|
+
"paquette.license_key" => "TEST-LICENSE-123",
|
|
36
|
+
"paquette.custom_field" => "custom_value"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
new_gem_path = Paquette::GemServer::GemRepacker.repack(@test_gem_path,
|
|
40
|
+
gemspec_extras: additional_metadata,
|
|
41
|
+
magic_comment_replacements: {})
|
|
42
|
+
|
|
43
|
+
assert File.exist?(new_gem_path)
|
|
44
|
+
assert new_gem_path.end_with?("-repacked.gem")
|
|
45
|
+
|
|
46
|
+
# Verify the metadata was added to the gem spec
|
|
47
|
+
verify_metadata_in_gem(new_gem_path, additional_metadata)
|
|
48
|
+
|
|
49
|
+
# Clean up
|
|
50
|
+
File.delete(new_gem_path) if File.exist?(new_gem_path)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_repack_with_personalizer_metadata
|
|
54
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
55
|
+
|
|
56
|
+
# Test that Personalizer-style metadata addition works
|
|
57
|
+
personalized_gem_path = create_personalized_gem
|
|
58
|
+
|
|
59
|
+
# Verify the metadata was added
|
|
60
|
+
verify_metadata_in_gem(personalized_gem_path, {"paquette.license_key" => "TEST-LICENSE-456"})
|
|
61
|
+
|
|
62
|
+
# Clean up
|
|
63
|
+
File.delete(personalized_gem_path) if File.exist?(personalized_gem_path)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_repack_with_file_injection
|
|
67
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
68
|
+
|
|
69
|
+
# Test injecting new files into the gem
|
|
70
|
+
files_to_inject = {
|
|
71
|
+
"LICENSE" => "MIT License\nCopyright (c) 2024 Test Company",
|
|
72
|
+
"README.md" => "# Test Gem\n\nThis is a test gem with injected files.",
|
|
73
|
+
"docs/CHANGELOG.md" => "# Changelog\n\n## 0.1.0\n- Initial release"
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
new_gem_path = Paquette::GemServer::GemRepacker.repack(@test_gem_path,
|
|
77
|
+
gemspec_extras: {},
|
|
78
|
+
magic_comment_replacements: {},
|
|
79
|
+
files: files_to_inject)
|
|
80
|
+
|
|
81
|
+
assert File.exist?(new_gem_path)
|
|
82
|
+
assert new_gem_path.end_with?("-repacked.gem")
|
|
83
|
+
|
|
84
|
+
# Verify the injected files exist in the repacked gem
|
|
85
|
+
verify_injected_files(new_gem_path, files_to_inject)
|
|
86
|
+
|
|
87
|
+
# Clean up
|
|
88
|
+
File.delete(new_gem_path) if File.exist?(new_gem_path)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_repack_with_file_replacement
|
|
92
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
93
|
+
|
|
94
|
+
# Test replacing existing files in the gem
|
|
95
|
+
files_to_replace = {
|
|
96
|
+
"lib/minuscule_test.rb" => "# Replaced content\nmodule MinusculeTest\n VERSION = '0.1.0-replaced'\nend"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
new_gem_path = Paquette::GemServer::GemRepacker.repack(@test_gem_path,
|
|
100
|
+
gemspec_extras: {},
|
|
101
|
+
magic_comment_replacements: {},
|
|
102
|
+
files: files_to_replace)
|
|
103
|
+
|
|
104
|
+
assert File.exist?(new_gem_path)
|
|
105
|
+
assert new_gem_path.end_with?("-repacked.gem")
|
|
106
|
+
|
|
107
|
+
# Verify the file was replaced
|
|
108
|
+
verify_injected_files(new_gem_path, files_to_replace)
|
|
109
|
+
|
|
110
|
+
# Clean up
|
|
111
|
+
File.delete(new_gem_path) if File.exist?(new_gem_path)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_repack_with_combined_features
|
|
115
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
116
|
+
|
|
117
|
+
# Test combining file injection with other features
|
|
118
|
+
files_to_inject = {
|
|
119
|
+
"LICENSE" => "MIT License\nCopyright (c) 2024 Test Company",
|
|
120
|
+
"docs/README.md" => "# Test Gem\n\nThis gem has been personalized."
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
magic_comment_replacements = {
|
|
124
|
+
"# paquette_license_info" => "LICENSE-INJECTED"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
gemspec_extras = {
|
|
128
|
+
"paquette.license_key" => "TEST-LICENSE-COMBINED"
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
new_gem_path = Paquette::GemServer::GemRepacker.repack(@test_gem_path,
|
|
132
|
+
gemspec_extras: gemspec_extras,
|
|
133
|
+
magic_comment_replacements: magic_comment_replacements,
|
|
134
|
+
files: files_to_inject)
|
|
135
|
+
|
|
136
|
+
assert File.exist?(new_gem_path)
|
|
137
|
+
assert new_gem_path.end_with?("-repacked.gem")
|
|
138
|
+
|
|
139
|
+
# Verify all features work together
|
|
140
|
+
verify_metadata_in_gem(new_gem_path, gemspec_extras)
|
|
141
|
+
verify_injected_files(new_gem_path, files_to_inject)
|
|
142
|
+
|
|
143
|
+
# Clean up
|
|
144
|
+
File.delete(new_gem_path) if File.exist?(new_gem_path)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def test_repack_with_magic_comment_replacements
|
|
148
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
149
|
+
|
|
150
|
+
# Test adding magic comment replacements
|
|
151
|
+
magic_comment_replacements = {
|
|
152
|
+
"# paquette_license_info" => "TEST-LICENSE-789",
|
|
153
|
+
"# paquette_custom_field" => "CUSTOM-VALUE-123"
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
new_gem_path = Paquette::GemServer::GemRepacker.repack(@test_gem_path,
|
|
157
|
+
gemspec_extras: {"paquette.license_key" => "TEST-LICENSE-789"},
|
|
158
|
+
magic_comment_replacements: magic_comment_replacements)
|
|
159
|
+
|
|
160
|
+
assert File.exist?(new_gem_path)
|
|
161
|
+
assert new_gem_path.end_with?("-repacked.gem")
|
|
162
|
+
|
|
163
|
+
# Verify the metadata was added to the gem spec
|
|
164
|
+
verify_metadata_in_gem(new_gem_path, {"paquette.license_key" => "TEST-LICENSE-789"})
|
|
165
|
+
|
|
166
|
+
# Clean up
|
|
167
|
+
File.delete(new_gem_path) if File.exist?(new_gem_path)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def test_personalizer_with_flexible_comment_replacements
|
|
171
|
+
assert File.exist?(@test_gem_path), "Test gem not found at #{@test_gem_path}"
|
|
172
|
+
|
|
173
|
+
# Test the Personalizer with custom magic comment replacements
|
|
174
|
+
dir_repository = Paquette::GemServer::DirectoryGemRepository.new(FIXTURE_GEMS_DIR)
|
|
175
|
+
|
|
176
|
+
custom_replacements = {
|
|
177
|
+
"# paquette_license_info" => "CUSTOM-LICENSE-123",
|
|
178
|
+
"# paquette_custom_field" => "CUSTOM-VALUE-456"
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
personalizer = Paquette::GemServer::Personalizer.new(dir_repository,
|
|
182
|
+
license_key: "CUSTOM-LICENSE-123",
|
|
183
|
+
magic_comment_replacements: custom_replacements)
|
|
184
|
+
|
|
185
|
+
# Get the personalized gem path
|
|
186
|
+
personalized_gem_path = personalizer.gem_file_path("minuscule_test", "0.1.0")
|
|
187
|
+
assert File.exist?(personalized_gem_path)
|
|
188
|
+
|
|
189
|
+
# Verify the metadata was added
|
|
190
|
+
verify_metadata_in_gem(personalized_gem_path, {"paquette.license_key" => "CUSTOM-LICENSE-123"})
|
|
191
|
+
|
|
192
|
+
# Clean up
|
|
193
|
+
File.delete(personalized_gem_path) if File.exist?(personalized_gem_path)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
private
|
|
197
|
+
|
|
198
|
+
def verify_repacking(gem_path, expected_random_chars)
|
|
199
|
+
# Create a temporary directory to unpack the new gem
|
|
200
|
+
temp_dir = Dir.mktmpdir("verify_repacking")
|
|
201
|
+
unpacked_dir = File.join(temp_dir, "unpacked")
|
|
202
|
+
FileUtils.mkdir_p(unpacked_dir)
|
|
203
|
+
|
|
204
|
+
begin
|
|
205
|
+
# Unpack the new gem
|
|
206
|
+
_, stderr, status = Open3.capture3("gem unpack #{gem_path} --target=#{unpacked_dir}")
|
|
207
|
+
assert status.success?, "Failed to unpack the repacked gem: #{stderr}"
|
|
208
|
+
|
|
209
|
+
# Find the unpacked gem directory
|
|
210
|
+
gem_dir = Dir.glob(File.join(unpacked_dir, "*")).find { |path| File.directory?(path) }
|
|
211
|
+
assert gem_dir, "Could not find unpacked gem directory"
|
|
212
|
+
|
|
213
|
+
# Check all Ruby files for the replacement
|
|
214
|
+
found_replacement = false
|
|
215
|
+
Dir.glob(File.join(gem_dir, "**", "*.rb")).each do |rb_file|
|
|
216
|
+
File.readlines(rb_file).each do |line|
|
|
217
|
+
if line.chomp == "# LIC#{expected_random_chars}"
|
|
218
|
+
found_replacement = true
|
|
219
|
+
end
|
|
220
|
+
# Ensure the original line is gone
|
|
221
|
+
refute_equal line.chomp, "# paquette_license_info", "Original line still present in #{rb_file}"
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
assert found_replacement, "Replacement line '# LIC#{expected_random_chars}' not found in any Ruby file"
|
|
226
|
+
ensure
|
|
227
|
+
FileUtils.rm_rf(temp_dir)
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def create_personalized_gem
|
|
232
|
+
# Create a personalized gem using the Personalizer approach
|
|
233
|
+
personalized_dir = File.join(Dir.tmpdir, "paquette_personalized")
|
|
234
|
+
FileUtils.mkdir_p(personalized_dir)
|
|
235
|
+
|
|
236
|
+
personalized_path = File.join(personalized_dir, "minuscule_test-0.1.0-personalized.gem")
|
|
237
|
+
|
|
238
|
+
Paquette::GemServer::GemRepacker.repack(@test_gem_path,
|
|
239
|
+
gemspec_extras: {"paquette.license_key" => "TEST-LICENSE-456"},
|
|
240
|
+
magic_comment_replacements: {"# paquette_license_info" => "TEST-LICENSE-456"})
|
|
241
|
+
|
|
242
|
+
# Move the repacked gem to our personalized location
|
|
243
|
+
temp_personalized = File.join(Dir.tmpdir, "minuscule_test-0.1.0-repacked.gem")
|
|
244
|
+
if File.exist?(temp_personalized)
|
|
245
|
+
FileUtils.mv(temp_personalized, personalized_path)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
personalized_path
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def verify_metadata_in_gem(gem_path, expected_metadata)
|
|
252
|
+
# Read the gem specification directly from the gem file
|
|
253
|
+
gem_package = Gem::Package.new(gem_path)
|
|
254
|
+
spec = gem_package.spec
|
|
255
|
+
|
|
256
|
+
# Verify each expected metadata key is present in the spec
|
|
257
|
+
expected_metadata.each do |key, value|
|
|
258
|
+
assert_equal value, spec.metadata[key], "Expected metadata key '#{key}' to have value '#{value}', but got '#{spec.metadata[key]}'"
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def verify_injected_files(gem_path, expected_files)
|
|
263
|
+
# Create a temporary directory to unpack the new gem
|
|
264
|
+
temp_dir = Dir.mktmpdir("verify_injected_files")
|
|
265
|
+
unpacked_dir = File.join(temp_dir, "unpacked")
|
|
266
|
+
FileUtils.mkdir_p(unpacked_dir)
|
|
267
|
+
|
|
268
|
+
begin
|
|
269
|
+
# Unpack the new gem
|
|
270
|
+
_, stderr, status = Open3.capture3("gem unpack #{gem_path} --target=#{unpacked_dir}")
|
|
271
|
+
assert status.success?, "Failed to unpack the gem: #{stderr}"
|
|
272
|
+
|
|
273
|
+
# Find the unpacked gem directory
|
|
274
|
+
gem_dir = Dir.glob(File.join(unpacked_dir, "*")).find { |path| File.directory?(path) }
|
|
275
|
+
assert gem_dir, "Could not find unpacked gem directory"
|
|
276
|
+
|
|
277
|
+
# Verify each expected file exists and has the correct content
|
|
278
|
+
expected_files.each do |file_path, expected_content|
|
|
279
|
+
full_file_path = File.join(gem_dir, file_path)
|
|
280
|
+
assert File.exist?(full_file_path), "Expected file '#{file_path}' not found in unpacked gem"
|
|
281
|
+
|
|
282
|
+
actual_content = File.read(full_file_path)
|
|
283
|
+
assert_equal expected_content, actual_content, "File '#{file_path}' content doesn't match expected content"
|
|
284
|
+
end
|
|
285
|
+
ensure
|
|
286
|
+
FileUtils.rm_rf(temp_dir)
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require_relative "../test_helper"
|
|
2
|
+
|
|
3
|
+
class PersonalizerMetadataTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
@gems_dir = FIXTURE_GEMS_DIR
|
|
6
|
+
@dir_repository = Paquette::GemServer::DirectoryGemRepository.new(@gems_dir)
|
|
7
|
+
@personalizer = Paquette::GemServer::Personalizer.new(@dir_repository, license_key: "TEST-LICENSE-789")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_personalizer_adds_license_metadata_to_gem_spec
|
|
11
|
+
skip "Test gem not found" unless @personalizer.gem_exists?("minuscule_test", "0.1.0")
|
|
12
|
+
|
|
13
|
+
# Get the personalized gem path
|
|
14
|
+
personalized_gem_path = @personalizer.gem_file_path("minuscule_test", "0.1.0")
|
|
15
|
+
assert File.exist?(personalized_gem_path)
|
|
16
|
+
|
|
17
|
+
# Read the gem specification and verify the license key metadata
|
|
18
|
+
gem_package = Gem::Package.new(personalized_gem_path)
|
|
19
|
+
spec = gem_package.spec
|
|
20
|
+
|
|
21
|
+
# Verify the license key is in the metadata
|
|
22
|
+
assert_equal "TEST-LICENSE-789", spec.metadata["paquette.license_key"], "Expected paquette.license_key metadata to be set"
|
|
23
|
+
|
|
24
|
+
# Verify the original gem doesn't have this metadata
|
|
25
|
+
original_gem_path = @dir_repository.gem_file_path("minuscule_test", "0.1.0")
|
|
26
|
+
original_gem_package = Gem::Package.new(original_gem_path)
|
|
27
|
+
original_spec = original_gem_package.spec
|
|
28
|
+
|
|
29
|
+
assert_nil original_spec.metadata["paquette.license_key"], "Original gem should not have paquette.license_key metadata"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_metadata_persistence_through_repository_stack
|
|
33
|
+
skip "Test gem not found" unless @personalizer.gem_exists?("minuscule_test", "0.1.0")
|
|
34
|
+
|
|
35
|
+
# Test that the metadata persists through the repository stack
|
|
36
|
+
personalized_repository = Paquette::GemServer::Personalizer.new(@dir_repository, license_key: "STACK-TEST-123")
|
|
37
|
+
gated_repository = Paquette::GemServer::ReadGatedRepository.new(personalized_repository) { |name:, version: nil| true }
|
|
38
|
+
|
|
39
|
+
# Get gem through the stack
|
|
40
|
+
gem_path = gated_repository.gem_file_path("minuscule_test", "0.1.0")
|
|
41
|
+
assert File.exist?(gem_path)
|
|
42
|
+
|
|
43
|
+
# Verify metadata is present
|
|
44
|
+
gem_package = Gem::Package.new(gem_path)
|
|
45
|
+
spec = gem_package.spec
|
|
46
|
+
|
|
47
|
+
assert_equal "STACK-TEST-123", spec.metadata["paquette.license_key"], "Expected paquette.license_key metadata to be set through repository stack"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require_relative "../test_helper"
|
|
2
|
+
|
|
3
|
+
class PersonalizerTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
@gems_dir = FIXTURE_GEMS_DIR
|
|
6
|
+
@dir_repository = Paquette::GemServer::DirectoryGemRepository.new(@gems_dir)
|
|
7
|
+
@personalizer = Paquette::GemServer::Personalizer.new(@dir_repository,
|
|
8
|
+
license_key: "TEST-LICENSE-123",
|
|
9
|
+
magic_comment_replacements: {"# paquette_license_info" => "TEST-LICENSE-123"})
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_personalizer_delegates_to_repository
|
|
13
|
+
# Test that basic repository methods still work
|
|
14
|
+
assert @personalizer.gem_names.include?("minuscule_test")
|
|
15
|
+
assert @personalizer.versions_for_gem("minuscule_test").include?("0.1.0")
|
|
16
|
+
assert @personalizer.gem_exists?("minuscule_test", "0.1.0")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_gem_file_path_returns_personalized_gem
|
|
20
|
+
skip "Test gem not found" unless @personalizer.gem_exists?("minuscule_test", "0.1.0")
|
|
21
|
+
|
|
22
|
+
# Get the personalized gem path
|
|
23
|
+
personalized_path = @personalizer.gem_file_path("minuscule_test", "0.1.0")
|
|
24
|
+
|
|
25
|
+
# Should be a different path than the original
|
|
26
|
+
original_path = @dir_repository.gem_file_path("minuscule_test", "0.1.0")
|
|
27
|
+
refute_equal original_path, personalized_path
|
|
28
|
+
|
|
29
|
+
# Should exist and be a file
|
|
30
|
+
assert File.exist?(personalized_path)
|
|
31
|
+
assert File.file?(personalized_path)
|
|
32
|
+
|
|
33
|
+
# Should have a different checksum than the original
|
|
34
|
+
require "digest"
|
|
35
|
+
original_checksum = Digest::SHA256.file(original_path).hexdigest
|
|
36
|
+
personalized_checksum = Digest::SHA256.file(personalized_path).hexdigest
|
|
37
|
+
refute_equal original_checksum, personalized_checksum
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_compact_info_uses_personalized_checksums
|
|
41
|
+
skip "Test gem not found" unless @personalizer.gem_exists?("minuscule_test", "0.1.0")
|
|
42
|
+
|
|
43
|
+
# Get compact info from personalizer
|
|
44
|
+
personalized_info = @personalizer.compact_info("minuscule_test")
|
|
45
|
+
|
|
46
|
+
# Get compact info from original repository
|
|
47
|
+
original_info = @dir_repository.compact_info("minuscule_test")
|
|
48
|
+
|
|
49
|
+
# Should have same number of versions
|
|
50
|
+
assert_equal original_info.length, personalized_info.length
|
|
51
|
+
|
|
52
|
+
# But checksums should be different
|
|
53
|
+
original_checksum = extract_checksum(original_info.first)
|
|
54
|
+
personalized_checksum = extract_checksum(personalized_info.first)
|
|
55
|
+
|
|
56
|
+
refute_equal original_checksum, personalized_checksum
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def extract_checksum(info_line)
|
|
62
|
+
if (match = info_line.match(/checksum:([a-f0-9]+)/))
|
|
63
|
+
match[1]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
require_relative "../test_helper"
|
|
2
|
+
|
|
3
|
+
class ReadGatedRepositoryTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
@gems_dir = FIXTURE_GEMS_DIR
|
|
6
|
+
@directory_repository = Paquette::GemServer::DirectoryGemRepository.new(@gems_dir)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_gem_names_with_all_gems_entitled
|
|
10
|
+
entitler = ->(name:, version: nil) { true }
|
|
11
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
12
|
+
|
|
13
|
+
assert_equal ["minuscule_test", "zip_kit"], repository.gem_names.sort
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_gem_names_with_only_zip_kit_entitled
|
|
17
|
+
entitler = ->(name:, version: nil) { name == "zip_kit" }
|
|
18
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
19
|
+
|
|
20
|
+
assert_equal ["zip_kit"], repository.gem_names
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_gem_names_with_no_gems_entitled
|
|
24
|
+
entitler = ->(name:, version: nil) { false }
|
|
25
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
26
|
+
|
|
27
|
+
assert_equal [], repository.gem_names
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_gem_versions_with_all_entitled
|
|
31
|
+
entitler = ->(name:, version: nil) { true }
|
|
32
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
33
|
+
|
|
34
|
+
versions = repository.gem_versions
|
|
35
|
+
assert_equal 3, versions.length
|
|
36
|
+
|
|
37
|
+
# standard:disable Style/HashSlice
|
|
38
|
+
zip_kit_versions = versions.select { |name, _| name == "zip_kit" }
|
|
39
|
+
# standard:enable Style/HashSlice
|
|
40
|
+
assert_equal 2, zip_kit_versions.length
|
|
41
|
+
assert_includes zip_kit_versions.map { |_, v| v }, "6.2.0"
|
|
42
|
+
assert_includes zip_kit_versions.map { |_, v| v }, "6.2.1"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_gem_versions_with_only_zip_kit_entitled
|
|
46
|
+
entitler = ->(name:, version: nil) { name == "zip_kit" }
|
|
47
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
48
|
+
|
|
49
|
+
versions = repository.gem_versions
|
|
50
|
+
assert_equal 2, versions.length
|
|
51
|
+
versions.each do |name, _|
|
|
52
|
+
assert_equal "zip_kit", name
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
zip_kit_versions = versions.map { |_, v| v }
|
|
56
|
+
assert_includes zip_kit_versions, "6.2.0"
|
|
57
|
+
assert_includes zip_kit_versions, "6.2.1"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_gem_versions_with_subset_of_zip_kit_versions_entitled
|
|
61
|
+
entitler = ->(name:, version: nil) do
|
|
62
|
+
name == "zip_kit" && (version.nil? || version == "6.2.0")
|
|
63
|
+
end
|
|
64
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
65
|
+
|
|
66
|
+
versions = repository.gem_versions
|
|
67
|
+
assert_equal 1, versions.length
|
|
68
|
+
assert_equal "zip_kit", versions.first.first
|
|
69
|
+
assert_equal "6.2.0", versions.first.last
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_versions_for_gem_with_all_versions_entitled
|
|
73
|
+
entitler = ->(name:, version: nil) { true }
|
|
74
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
75
|
+
|
|
76
|
+
zip_kit_versions = repository.versions_for_gem("zip_kit")
|
|
77
|
+
assert_equal 2, zip_kit_versions.length
|
|
78
|
+
assert_includes zip_kit_versions, "6.2.0"
|
|
79
|
+
assert_includes zip_kit_versions, "6.2.1"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_versions_for_gem_with_only_zip_kit_entitled
|
|
83
|
+
entitler = ->(name:, version: nil) { name == "zip_kit" }
|
|
84
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
85
|
+
|
|
86
|
+
zip_kit_versions = repository.versions_for_gem("zip_kit")
|
|
87
|
+
assert_equal 2, zip_kit_versions.length
|
|
88
|
+
assert_includes zip_kit_versions, "6.2.0"
|
|
89
|
+
assert_includes zip_kit_versions, "6.2.1"
|
|
90
|
+
|
|
91
|
+
assert_equal [], repository.versions_for_gem("minuscule_test")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_versions_for_gem_with_subset_of_versions_entitled
|
|
95
|
+
entitler = ->(name:, version: nil) do
|
|
96
|
+
name == "zip_kit" && (version.nil? || version == "6.2.0")
|
|
97
|
+
end
|
|
98
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
99
|
+
|
|
100
|
+
zip_kit_versions = repository.versions_for_gem("zip_kit")
|
|
101
|
+
assert_equal ["6.2.0"], zip_kit_versions
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def test_versions_for_gem_with_gem_not_entitled
|
|
105
|
+
entitler = ->(name:, version: nil) { name == "zip_kit" }
|
|
106
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
107
|
+
|
|
108
|
+
assert_equal [], repository.versions_for_gem("minuscule_test")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_gem_file_path_with_entitled_version
|
|
112
|
+
entitler = ->(name:, version: nil) { true }
|
|
113
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
114
|
+
|
|
115
|
+
expected_path = File.join(@gems_dir, "zip_kit", "zip_kit-6.2.0.gem")
|
|
116
|
+
assert_equal expected_path, repository.gem_file_path("zip_kit", "6.2.0")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_gem_file_path_with_not_entitled_version
|
|
120
|
+
entitler = ->(name:, version: nil) do
|
|
121
|
+
name == "zip_kit" && (version.nil? || version == "6.2.0")
|
|
122
|
+
end
|
|
123
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
124
|
+
|
|
125
|
+
expected_path = File.join(@gems_dir, "zip_kit", "zip_kit-6.2.0.gem")
|
|
126
|
+
assert_equal expected_path, repository.gem_file_path("zip_kit", "6.2.0")
|
|
127
|
+
|
|
128
|
+
assert_nil repository.gem_file_path("zip_kit", "6.2.1")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_gem_file_path_with_not_entitled_gem
|
|
132
|
+
entitler = ->(name:, version: nil) { name == "zip_kit" }
|
|
133
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
134
|
+
|
|
135
|
+
assert_nil repository.gem_file_path("minuscule_test", "0.1.0")
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def test_gem_exists_with_entitled_version
|
|
139
|
+
entitler = ->(name:, version: nil) { true }
|
|
140
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
141
|
+
|
|
142
|
+
assert repository.gem_exists?("zip_kit", "6.2.0")
|
|
143
|
+
assert repository.gem_exists?("zip_kit", "6.2.1")
|
|
144
|
+
assert repository.gem_exists?("minuscule_test", "0.1.0")
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def test_gem_exists_with_not_entitled_version
|
|
148
|
+
entitler = ->(name:, version: nil) do
|
|
149
|
+
name == "zip_kit" && (version.nil? || version == "6.2.0")
|
|
150
|
+
end
|
|
151
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
152
|
+
|
|
153
|
+
assert repository.gem_exists?("zip_kit", "6.2.0")
|
|
154
|
+
assert_nil repository.gem_exists?("zip_kit", "6.2.1")
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_gem_exists_with_not_entitled_gem
|
|
158
|
+
entitler = ->(name:, version: nil) { name == "zip_kit" }
|
|
159
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
160
|
+
|
|
161
|
+
assert_nil repository.gem_exists?("minuscule_test", "0.1.0")
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_compact_info_with_entitled_gem
|
|
165
|
+
entitler = ->(name:, version: nil) { true }
|
|
166
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
167
|
+
|
|
168
|
+
info = repository.compact_info("zip_kit")
|
|
169
|
+
assert info.is_a?(Array)
|
|
170
|
+
assert_equal 2, info.length
|
|
171
|
+
info.each do |line|
|
|
172
|
+
assert_match(/^\S+\s+\|checksum:[a-f0-9]{64},ruby:.+$/, line)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
versions = info.map { |line| line.split(" ")[0] }
|
|
176
|
+
assert_includes versions, "6.2.0"
|
|
177
|
+
assert_includes versions, "6.2.1"
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def test_compact_info_with_not_entitled_gem
|
|
181
|
+
entitler = ->(name:, version: nil) { name == "zip_kit" }
|
|
182
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
183
|
+
|
|
184
|
+
info = repository.compact_info("zip_kit")
|
|
185
|
+
assert info.is_a?(Array)
|
|
186
|
+
assert_equal 2, info.length
|
|
187
|
+
|
|
188
|
+
assert_nil repository.compact_info("minuscule_test")
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_compact_info_with_subset_of_versions_entitled
|
|
192
|
+
entitler = ->(name:, version: nil) do
|
|
193
|
+
name == "zip_kit" && (version.nil? || version == "6.2.0")
|
|
194
|
+
end
|
|
195
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
196
|
+
|
|
197
|
+
info = repository.compact_info("zip_kit")
|
|
198
|
+
assert info.is_a?(Array)
|
|
199
|
+
assert_equal 1, info.length
|
|
200
|
+
assert_equal "6.2.0", info.first.split(" ")[0]
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def test_add_gem_raises_write_not_allowed
|
|
204
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository) { |**| true }
|
|
205
|
+
|
|
206
|
+
assert_raises(Paquette::GemServer::ReadGatedRepository::WriteNotAllowed) do
|
|
207
|
+
repository.add_gem("anything")
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def test_yank_gem_raises_write_not_allowed
|
|
212
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository) { |**| true }
|
|
213
|
+
|
|
214
|
+
assert_raises(Paquette::GemServer::ReadGatedRepository::WriteNotAllowed) do
|
|
215
|
+
repository.yank_gem("zip_kit", "6.2.0")
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_delegated_methods_still_work
|
|
220
|
+
# Test that methods not overridden in ReadGatedRepository still delegate correctly
|
|
221
|
+
entitler = ->(name:, version: nil) { true }
|
|
222
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
223
|
+
|
|
224
|
+
spec = repository.gem_spec("zip_kit", "6.2.0")
|
|
225
|
+
refute_nil spec
|
|
226
|
+
assert_equal "zip_kit", spec.name
|
|
227
|
+
assert_equal "6.2.0", spec.version.to_s
|
|
228
|
+
|
|
229
|
+
deps = repository.gem_dependencies("zip_kit", "6.2.0")
|
|
230
|
+
assert deps.is_a?(Array)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def test_complex_entitlement_logic
|
|
234
|
+
# Allow zip_kit >= 6.2.1 and all minuscule_test
|
|
235
|
+
entitler = ->(name:, version: nil) do
|
|
236
|
+
if name == "zip_kit"
|
|
237
|
+
version.nil? || Gem::Version.new(version) >= Gem::Version.new("6.2.1")
|
|
238
|
+
else
|
|
239
|
+
name == "minuscule_test"
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
repository = Paquette::GemServer::ReadGatedRepository.new(@directory_repository, &entitler)
|
|
243
|
+
|
|
244
|
+
names = repository.gem_names
|
|
245
|
+
assert_includes names, "zip_kit"
|
|
246
|
+
assert_includes names, "minuscule_test"
|
|
247
|
+
|
|
248
|
+
zip_kit_versions = repository.versions_for_gem("zip_kit")
|
|
249
|
+
assert_equal ["6.2.1"], zip_kit_versions
|
|
250
|
+
|
|
251
|
+
minuscule_versions = repository.versions_for_gem("minuscule_test")
|
|
252
|
+
assert_equal ["0.1.0"], minuscule_versions
|
|
253
|
+
end
|
|
254
|
+
end
|