lapis-minecraft-versioning 0.5.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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +18 -0
  3. data/.gitignore +151 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +1156 -0
  6. data/.travis.yml +4 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.md +16 -0
  9. data/README.md +83 -0
  10. data/Rakefile +28 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +7 -0
  13. data/lapis-minecraft-versioning.gemspec +35 -0
  14. data/lib/lapis/minecraft/version.rb +89 -0
  15. data/lib/lapis/minecraft/versioning.rb +26 -0
  16. data/lib/lapis/minecraft/versioning/asset.rb +44 -0
  17. data/lib/lapis/minecraft/versioning/asset_index.rb +61 -0
  18. data/lib/lapis/minecraft/versioning/basic.rb +56 -0
  19. data/lib/lapis/minecraft/versioning/detailed.rb +69 -0
  20. data/lib/lapis/minecraft/versioning/launcher_properties.rb +48 -0
  21. data/lib/lapis/minecraft/versioning/library.rb +51 -0
  22. data/lib/lapis/minecraft/versioning/manifest.rb +49 -0
  23. data/lib/lapis/minecraft/versioning/marshalling.rb +15 -0
  24. data/lib/lapis/minecraft/versioning/marshalling/asset_index_parser.rb +41 -0
  25. data/lib/lapis/minecraft/versioning/marshalling/manifest_parser.rb +66 -0
  26. data/lib/lapis/minecraft/versioning/marshalling/version_parser.rb +204 -0
  27. data/lib/lapis/minecraft/versioning/meta_server.rb +52 -0
  28. data/lib/lapis/minecraft/versioning/os_rule.rb +45 -0
  29. data/lib/lapis/minecraft/versioning/resource.rb +44 -0
  30. data/lib/lapis/minecraft/versioning/resource_set.rb +61 -0
  31. data/lib/lapis/minecraft/versioning/rule.rb +32 -0
  32. data/lib/lapis/minecraft/versioning/version.rb +7 -0
  33. data/lib/lapis/minecraft/versioning/version_list.rb +64 -0
  34. data/spec/factories/asset_factory.rb +11 -0
  35. data/spec/factories/asset_index_document_factory.rb +25 -0
  36. data/spec/factories/asset_index_factory.rb +15 -0
  37. data/spec/factories/basic_factory.rb +28 -0
  38. data/spec/factories/detailed_factory.rb +16 -0
  39. data/spec/factories/launcher_properties_factory.rb +11 -0
  40. data/spec/factories/library_factory.rb +21 -0
  41. data/spec/factories/manifest_document_factory.rb +48 -0
  42. data/spec/factories/manifest_factory.rb +12 -0
  43. data/spec/factories/meta_server_mock_factory.rb +33 -0
  44. data/spec/factories/os_rule_factory.rb +30 -0
  45. data/spec/factories/resource_factory.rb +32 -0
  46. data/spec/factories/resource_set_factory.rb +16 -0
  47. data/spec/factories/rule_factory.rb +17 -0
  48. data/spec/factories/version_document_factory.rb +176 -0
  49. data/spec/factories/version_factory.rb +18 -0
  50. data/spec/lapis/minecraft/version_spec.rb +181 -0
  51. data/spec/lapis/minecraft/versioning/asset_index_spec.rb +89 -0
  52. data/spec/lapis/minecraft/versioning/asset_spec.rb +65 -0
  53. data/spec/lapis/minecraft/versioning/basic_spec.rb +75 -0
  54. data/spec/lapis/minecraft/versioning/detailed_spec.rb +175 -0
  55. data/spec/lapis/minecraft/versioning/launcher_properties_spec.rb +73 -0
  56. data/spec/lapis/minecraft/versioning/library_spec.rb +91 -0
  57. data/spec/lapis/minecraft/versioning/manifest_spec.rb +71 -0
  58. data/spec/lapis/minecraft/versioning/marshalling/asset_index_parser_spec.rb +27 -0
  59. data/spec/lapis/minecraft/versioning/marshalling/manifest_parser_spec.rb +74 -0
  60. data/spec/lapis/minecraft/versioning/marshalling/version_parser_spec.rb +101 -0
  61. data/spec/lapis/minecraft/versioning/meta_server_spec.rb +59 -0
  62. data/spec/lapis/minecraft/versioning/os_rule_spec.rb +73 -0
  63. data/spec/lapis/minecraft/versioning/resource_set_spec.rb +87 -0
  64. data/spec/lapis/minecraft/versioning/resource_spec.rb +55 -0
  65. data/spec/lapis/minecraft/versioning/rule_spec.rb +36 -0
  66. data/spec/lapis/minecraft/versioning/version_list_spec.rb +66 -0
  67. data/spec/spec_helper.rb +90 -0
  68. data/spec/time_helper.rb +39 -0
  69. metadata +289 -0
@@ -0,0 +1,48 @@
1
+ require 'json'
2
+
3
+ FactoryGirl.define do
4
+ factory :manifest_document_entry, class: Array do
5
+ transient do
6
+ version { build(:basic) }
7
+ end
8
+
9
+ initialize_with do
10
+ {
11
+ :id => version.id,
12
+ :time => version.time.json_time,
13
+ :releaseTime => version.time.json_time,
14
+ :url => version.url,
15
+ :type => case version.type
16
+ when :alpha
17
+ 'old_alpha'
18
+ when :beta
19
+ 'old_beta'
20
+ else
21
+ version.type.to_s
22
+ end
23
+ }
24
+ end
25
+ end
26
+
27
+ ManifestStruct = Struct.new(:source, :document)
28
+
29
+ factory :manifest_document, class: ManifestStruct do
30
+ transient do
31
+ source { build(:manifest) }
32
+ structure do
33
+ {
34
+ :latest => {
35
+ :release => source.latest_release.id,
36
+ :snapshot => source.latest_snapshot.id
37
+ },
38
+ :versions => source.map do |version|
39
+ build(:manifest_document_entry, :version => version)
40
+ end
41
+ }
42
+ end
43
+ json { structure.to_json }
44
+ end
45
+
46
+ initialize_with { new(source, json) }
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ FactoryGirl.define do
2
+ factory :manifest, class: Lapis::Minecraft::Versioning::Manifest do
3
+ transient do
4
+ version_count 5
5
+ versions { build_list(:basic, version_count) }
6
+ latest_release_id { versions.first.id }
7
+ latest_snapshot_id { versions.last.id }
8
+ end
9
+
10
+ initialize_with { new(versions, latest_release_id, latest_snapshot_id) }
11
+ end
12
+ end
@@ -0,0 +1,33 @@
1
+ # FIXME: Implement proper mocking.
2
+ class MetaServerMock
3
+ def initialize(manifest, details, assets)
4
+ @manifest = manifest
5
+ @details = details
6
+ @assets = assets.freeze
7
+ end
8
+
9
+ def get_manifest(_)
10
+ @manifest
11
+ end
12
+
13
+ def get_details(_)
14
+ @details
15
+ end
16
+
17
+ def get_assets(_)
18
+ @assets
19
+ end
20
+ end
21
+
22
+ FactoryGirl.define do
23
+ factory :meta_server_mock, :class => MetaServerMock do
24
+ transient do
25
+ assets { build_list(:asset, 20) }
26
+ asset_index { build(:asset_index, :assets => assets) }
27
+ detailed { build(:detailed, :asset_index => asset_index) }
28
+ manifest { build(:manifest) }
29
+ end
30
+
31
+ initialize_with { new(manifest, detailed, assets) }
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ FactoryGirl.define do
2
+ factory :os_rule, parent: :rule, class: Lapis::Minecraft::Versioning::OSRule do
3
+ transient do
4
+ os_type :osx
5
+ os_version '^10\\.5\\.\\d$'
6
+ end
7
+
8
+ trait :windows do
9
+ os_type :windows
10
+ end
11
+
12
+ trait :linux do
13
+ os_type :linux
14
+ end
15
+
16
+ trait :osx do
17
+ os_type :osx
18
+ end
19
+
20
+ trait :has_version do
21
+ os_version '^10\\.5\\.\\d$'
22
+ end
23
+
24
+ trait :no_version do
25
+ os_version nil
26
+ end
27
+
28
+ initialize_with { new(is_allowed, os_type, os_version) }
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ FactoryGirl.define do
2
+ factory :resource, parent: :asset, aliases: [:download], class: Lapis::Minecraft::Versioning::Resource do
3
+ transient do
4
+ sequence(:url) { |n| "http://example.com/minecraft/resources/#{n}.png" }
5
+ classifier 'artifact'
6
+ end
7
+
8
+ trait :client do
9
+ classifier 'client'
10
+ path nil
11
+ end
12
+
13
+ trait :server do
14
+ classifier 'server'
15
+ path nil
16
+ end
17
+
18
+ trait :windows do
19
+ classifier 'natives-windows'
20
+ end
21
+
22
+ trait :linux do
23
+ classifier 'natives-linux'
24
+ end
25
+
26
+ trait :osx do
27
+ classifier 'natives-osx'
28
+ end
29
+
30
+ initialize_with { new(url, size, sha1, path, classifier) }
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ FactoryGirl.define do
2
+ factory :resource_set, class: Lapis::Minecraft::Versioning::ResourceSet do
3
+ transient do
4
+ windows { build(:resource, :windows) }
5
+ linux { build(:resource, :linux) }
6
+ osx { build(:resource, :osx) }
7
+ artifact { build(:resource) }
8
+ windows_classifier { windows.classifier }
9
+ linux_classifier { linux.classifier }
10
+ osx_classifier { osx.classifier }
11
+ resources { [artifact, windows, linux, osx] }
12
+ end
13
+
14
+ initialize_with { new(resources, windows_classifier, linux_classifier, osx_classifier) }
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ FactoryGirl.define do
2
+ factory :rule, class: Lapis::Minecraft::Versioning::Rule do
3
+ transient do
4
+ is_allowed true
5
+ end
6
+
7
+ trait :allow do
8
+ is_allowed true
9
+ end
10
+
11
+ trait :disallow do
12
+ is_allowed false
13
+ end
14
+
15
+ initialize_with { new(is_allowed) }
16
+ end
17
+ end
@@ -0,0 +1,176 @@
1
+ require 'json'
2
+
3
+ FactoryGirl.define do
4
+ factory :asset_index_document_entry, class: Hash do
5
+ transient do
6
+ source { build(:detailed) }
7
+ end
8
+
9
+ initialize_with do
10
+ {
11
+ :id => source.asset_index.id,
12
+ :sha1 => source.asset_index.sha1,
13
+ :size => source.asset_index.size,
14
+ :url => source.asset_index.url,
15
+ :totalSize => source.asset_index.total_size
16
+ }
17
+ end
18
+ end
19
+
20
+ factory :download_document_entry, class: Array do
21
+ transient do
22
+ download { build(:download) }
23
+ end
24
+
25
+ initialize_with do
26
+ hash = {
27
+ :sha1 => download.sha1,
28
+ :size => download.size,
29
+ :url => download.url
30
+ }
31
+ hash[:path] = download.path if download.path
32
+ [download.classifier, hash]
33
+ end
34
+ end
35
+
36
+ factory :downloads_document_entry, class: Hash do
37
+ transient do
38
+ downloads { build_list(:download, 3) }
39
+ end
40
+
41
+ initialize_with do
42
+ Hash[downloads.map { |download| build(:download_document_entry, :download => download) }]
43
+ end
44
+ end
45
+
46
+ factory :resources_document_entry, class: Hash do
47
+ transient do
48
+ resources { build(:resource_set) }
49
+ end
50
+
51
+ initialize_with do
52
+ hash = {
53
+ :classifiers => Hash[resources.resources.reject do |resource|
54
+ resource.classifier == 'artifact'
55
+ end.map do |resource|
56
+ build(:download_document_entry, :download => resource)
57
+ end]
58
+ }
59
+ hash.delete(:classifiers) if hash[:classifiers].empty?
60
+ if (artifact = resources.resources.find { |resource| resource.classifier == 'artifact' })
61
+ hash[:artifact] = {
62
+ :sha1 => artifact.sha1,
63
+ :size => artifact.size,
64
+ :url => artifact.url
65
+ }
66
+ hash[:artifact][:path] = artifact.path if artifact.path
67
+ end
68
+ hash
69
+ end
70
+ end
71
+
72
+ factory :rule_document_entry, class: Hash do
73
+ transient do
74
+ rule { build(:rule) }
75
+ end
76
+
77
+ initialize_with do
78
+ hash = {
79
+ :action => rule.allowed? ? 'allow' : 'disallow'
80
+ }
81
+ if rule.is_a? Lapis::Minecraft::Versioning::OSRule
82
+ hash[:os] = { :name => rule.os_type }
83
+ version_regex = rule.os_version.source
84
+ unless version_regex.empty?
85
+ hash[:os][:version] = version_regex
86
+ end
87
+ end
88
+ hash
89
+ end
90
+ end
91
+
92
+ factory :rules_document_entry, class: Array do
93
+ transient do
94
+ rules { build_list(:rule, 2) }
95
+ end
96
+
97
+ initialize_with do
98
+ rules.map { |rule| build(:rule_document_entry, :rule => rule) }
99
+ end
100
+ end
101
+
102
+ factory :library_document_entry, class: Hash do
103
+ transient do
104
+ library { build(:library) }
105
+ end
106
+
107
+ initialize_with do
108
+ hash = {
109
+ :name => library.name,
110
+ :downloads => build(:resources_document_entry, :resources => library.resources)
111
+ }
112
+ if library.resources.windows_classifier || library.resources.linux_classifier || library.resources.osx_classifer
113
+ hash[:natives] = {}
114
+ if library.resources.windows_classifier
115
+ hash[:natives][:windows] = library.resources.windows_classifier
116
+ end
117
+ if library.resources.linux_classifier
118
+ hash[:natives][:linux] = library.resources.linux_classifier
119
+ end
120
+ if library.resources.osx_classifier
121
+ hash[:natives][:osx] = library.resources.osx_classifier
122
+ end
123
+ end
124
+ if library.rules.any?
125
+ hash[:rules] = build(:rules_document_entry, :rules => library.rules)
126
+ end
127
+ if library.exclude_paths.any?
128
+ hash[:extract] = { :exclude => library.exclude_paths }
129
+ end
130
+ hash
131
+ end
132
+ end
133
+
134
+ factory :libraries_document_entry, class: Array do
135
+ transient do
136
+ source { build(:detailed) }
137
+ end
138
+
139
+ initialize_with do
140
+ source.libraries.map { |library| build(:library_document_entry, :library => library) }
141
+ end
142
+ end
143
+
144
+ VersionStruct = Struct.new(:source, :document)
145
+
146
+ factory :version_document, class: VersionStruct do
147
+ transient do
148
+ source { build(:detailed) }
149
+ structure do
150
+ {
151
+ :assetIndex => build(:asset_index_document_entry, :source => source),
152
+ :assets => source.asset_index.id,
153
+ :downloads => build(:downloads_document_entry, :downloads => source.downloads),
154
+ :id => source.id,
155
+ :libraries => build(:libraries_document_entry, :source => source),
156
+ :mainClass => source.launcher_properties.main_class,
157
+ :minecraftArguments => source.launcher_properties.arguments.join(' '),
158
+ :minimumLauncherVersion => source.launcher_properties.minimum_version,
159
+ :releaseTime => source.time.json_time,
160
+ :time => source.time.json_time,
161
+ :type => case source.type
162
+ when :alpha
163
+ 'old_alpha'
164
+ when :beta
165
+ 'old_beta'
166
+ else
167
+ source.type.to_s
168
+ end
169
+ }
170
+ end
171
+ json { structure.to_json }
172
+ end
173
+
174
+ initialize_with { new(source, json) }
175
+ end
176
+ end
@@ -0,0 +1,18 @@
1
+ FactoryGirl.define do
2
+ factory :version, parent: :basic, class: Lapis::Minecraft::Version do
3
+ transient do
4
+ assets { build_list(:asset, 20) }
5
+ asset_index { build(:asset_index, :assets => assets) }
6
+ downloads { [build(:download, :client), build(:download, :server), build(:resource)] }
7
+ libraries { build_list(:library, 5) }
8
+ launcher_properties { build(:launcher) }
9
+ detailed { build(:detailed, :assets => assets, :asset_index => asset_index, :downloads => downloads, :libraries => libraries, :launcher_properties => launcher_properties) }
10
+ meta_server { build(:meta_server_mock, :assets => assets, :detailed => detailed) }
11
+ end
12
+
13
+ initialize_with do
14
+ basic = Lapis::Minecraft::Versioning::Basic.new(id, type, time, url)
15
+ new(basic, meta_server)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,181 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ RSpec.describe Lapis::Minecraft::Version do
4
+
5
+ describe '#id' do
6
+ let(:id) { 'beta1.8' }
7
+ let(:version) { build(:version, :id => id) }
8
+ subject { version.id }
9
+
10
+ it 'is the expected value' do
11
+ is_expected.to eq id
12
+ end
13
+
14
+ it 'is frozen' do
15
+ is_expected.to be_frozen
16
+ end
17
+ end
18
+
19
+ describe '#type' do
20
+ let(:type) { :beta }
21
+ let(:version) { build(:version, :type => type) }
22
+ subject { version.type }
23
+
24
+ it 'is the expected value' do
25
+ is_expected.to eq type
26
+ end
27
+ end
28
+
29
+ describe '#time' do
30
+ let(:time) { 3.years.ago }
31
+ let(:version) { build(:version, :time => time) }
32
+ subject { version.time }
33
+
34
+ it 'is the expected value' do
35
+ is_expected.to eq time
36
+ end
37
+ end
38
+
39
+ describe '#url' do
40
+ let(:url) { 'https://example.com/minecraft/versions/beta1.8.json' }
41
+ let(:version) { build(:version, :url => url) }
42
+ subject { version.url }
43
+
44
+ it 'is the expected value' do
45
+ is_expected.to eq url
46
+ end
47
+
48
+ it 'is frozen' do
49
+ is_expected.to be_frozen
50
+ end
51
+ end
52
+
53
+ describe '#asset_index' do
54
+ let(:asset_index) { build(:asset_index) }
55
+ let(:version) { build(:version, :asset_index => asset_index) }
56
+ subject { version.asset_index }
57
+
58
+ it 'retrieves the expected value' do
59
+ is_expected.to eq asset_index
60
+ end
61
+ end
62
+
63
+ describe '#assets' do
64
+ let(:assets) { build_list(:asset, 5) }
65
+ let(:version) { build(:version, :assets => assets) }
66
+ subject { version.assets }
67
+
68
+ it 'retrieves the expected items' do
69
+ is_expected.to contain_exactly(*assets)
70
+ end
71
+
72
+ it 'is frozen' do
73
+ is_expected.to be_frozen
74
+ end
75
+ end
76
+
77
+ describe '#downloads' do
78
+ let(:downloads) { build_list(:download, 5) }
79
+ let(:version) { build(:version, :downloads => downloads) }
80
+ subject { version.downloads }
81
+
82
+ it 'retrieves the expected items' do
83
+ is_expected.to contain_exactly(*downloads)
84
+ end
85
+
86
+ it 'is frozen' do
87
+ is_expected.to be_frozen
88
+ end
89
+ end
90
+
91
+ describe '#client_download' do
92
+ let(:version) { build(:version, :downloads => downloads) }
93
+ subject { version.client_download }
94
+
95
+ context 'with a client provided' do
96
+ let(:client) { build(:download, :client) }
97
+ let(:downloads) { build_list(:download, 3) << client }
98
+
99
+ it 'finds the client' do
100
+ is_expected.to be client
101
+ end
102
+ end
103
+
104
+ context 'without a client provided' do
105
+ let(:downloads) { build_list(:download, 3) }
106
+
107
+ it 'returns nil' do
108
+ is_expected.to eq nil
109
+ end
110
+ end
111
+ end
112
+
113
+ describe '#server_download' do
114
+ let(:version) { build(:version, :downloads => downloads) }
115
+ subject { version.server_download }
116
+
117
+ context 'with a server provided' do
118
+ let(:server) { build(:download, :server) }
119
+ let(:downloads) { build_list(:download, 3) << server }
120
+
121
+ it 'finds the server' do
122
+ is_expected.to be server
123
+ end
124
+ end
125
+
126
+ context 'without a server provided' do
127
+ let(:downloads) { build_list(:download, 3) }
128
+
129
+ it 'returns nil' do
130
+ is_expected.to eq nil
131
+ end
132
+ end
133
+ end
134
+
135
+ describe '#libraries' do
136
+ let(:libraries) { build_list(:library, 5) }
137
+ let(:version) { build(:version, :libraries => libraries) }
138
+ subject { version.libraries }
139
+
140
+ it 'retrieves the expected items' do
141
+ is_expected.to contain_exactly(*libraries)
142
+ end
143
+
144
+ it 'is frozen' do
145
+ is_expected.to be_frozen
146
+ end
147
+ end
148
+
149
+ describe '#launcher_properties' do
150
+ let(:launcher) { build(:launcher) }
151
+ let(:version) { build(:version, :launcher_properties => launcher) }
152
+ subject { version.launcher_properties }
153
+
154
+ it 'retrieves the expected value' do
155
+ is_expected.to eq launcher
156
+ end
157
+ end
158
+
159
+ describe '#==' do
160
+ subject { version_1 == version_2 }
161
+
162
+ context 'with identical versions' do
163
+ let(:version_1) { build(:version) }
164
+ let(:version_2) { version_1.dup } # Too difficult to make a proper copy.
165
+
166
+ it 'is true' do
167
+ is_expected.to be true
168
+ end
169
+ end
170
+
171
+ context 'with different versions' do
172
+ let(:version_1) { build(:version) }
173
+ let(:version_2) { build(:version, :id => version_1.id + '-foobar') }
174
+
175
+ it 'is false' do
176
+ is_expected.to be false
177
+ end
178
+ end
179
+ end
180
+
181
+ end