gemstash 2.0.0 → 2.2.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 +4 -4
- data/CHANGELOG.md +57 -0
- data/exe/gemstash +3 -0
- data/lib/gemstash/api_key_authorization.rb +3 -0
- data/lib/gemstash/authorization.rb +7 -3
- data/lib/gemstash/cache.rb +42 -2
- data/lib/gemstash/cli/authorize.rb +5 -5
- data/lib/gemstash/cli/base.rb +4 -1
- data/lib/gemstash/cli/setup.rb +19 -4
- data/lib/gemstash/cli/start.rb +4 -1
- data/lib/gemstash/cli/status.rb +2 -0
- data/lib/gemstash/cli/stop.rb +2 -0
- data/lib/gemstash/cli.rb +2 -0
- data/lib/gemstash/config.ru +3 -3
- data/lib/gemstash/configuration.rb +8 -2
- data/lib/gemstash/db/authorization.rb +2 -0
- data/lib/gemstash/db/cached_rubygem.rb +3 -0
- data/lib/gemstash/db/dependency.rb +2 -0
- data/lib/gemstash/db/rubygem.rb +3 -0
- data/lib/gemstash/db/upstream.rb +3 -0
- data/lib/gemstash/db/version.rb +3 -0
- data/lib/gemstash/db.rb +3 -0
- data/lib/gemstash/dependencies.rb +6 -2
- data/lib/gemstash/env.rb +24 -4
- data/lib/gemstash/gem_fetcher.rb +4 -2
- data/lib/gemstash/gem_pusher.rb +7 -5
- data/lib/gemstash/gem_source/dependency_caching.rb +4 -4
- data/lib/gemstash/gem_source/private_source.rb +6 -3
- data/lib/gemstash/gem_source/rack_middleware.rb +3 -0
- data/lib/gemstash/gem_source/upstream_source.rb +9 -3
- data/lib/gemstash/gem_source.rb +4 -2
- data/lib/gemstash/gem_yanker.rb +4 -0
- data/lib/gemstash/health.rb +2 -0
- data/lib/gemstash/http_client.rb +12 -4
- data/lib/gemstash/logging.rb +3 -1
- data/lib/gemstash/man/gemstash-authorize.1.txt +0 -65
- data/lib/gemstash/man/gemstash-configuration.5.txt +0 -65
- data/lib/gemstash/man/gemstash-customize.7.txt +0 -65
- data/lib/gemstash/man/gemstash-debugging.7.txt +0 -65
- data/lib/gemstash/man/gemstash-deploy.7.txt +0 -65
- data/lib/gemstash/man/gemstash-mirror.7.txt +0 -65
- data/lib/gemstash/man/gemstash-multiple-sources.7.txt +0 -65
- data/lib/gemstash/man/gemstash-private-gems.7.txt +0 -65
- data/lib/gemstash/man/gemstash-readme.7.txt +0 -65
- data/lib/gemstash/man/gemstash-setup.1.txt +0 -65
- data/lib/gemstash/man/gemstash-start.1.txt +0 -65
- data/lib/gemstash/man/gemstash-status.1.txt +0 -65
- data/lib/gemstash/man/gemstash-stop.1.txt +0 -65
- data/lib/gemstash/man/gemstash-version.1.txt +0 -65
- data/lib/gemstash/migrations/01_gem_dependencies.rb +2 -0
- data/lib/gemstash/migrations/02_authorizations.rb +2 -0
- data/lib/gemstash/migrations/03_cached_gems.rb +2 -0
- data/lib/gemstash/migrations/04_health_tests.rb +2 -0
- data/lib/gemstash/puma.rb +2 -0
- data/lib/gemstash/rack_env_rewriter.rb +11 -2
- data/lib/gemstash/specs_builder.rb +5 -1
- data/lib/gemstash/storage.rb +17 -7
- data/lib/gemstash/upstream.rb +8 -5
- data/lib/gemstash/version.rb +4 -2
- data/lib/gemstash/web.rb +8 -4
- data/lib/gemstash.rb +3 -1
- metadata +40 -133
data/lib/gemstash/gem_fetcher.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
require "set"
|
3
5
|
|
4
6
|
module Gemstash
|
5
|
-
|
7
|
+
# :nodoc:
|
6
8
|
class GemFetcher
|
7
9
|
def initialize(http_client)
|
8
10
|
@http_client = http_client
|
9
|
-
@valid_headers = Set.new([
|
11
|
+
@valid_headers = Set.new(%w[etag content-type content-length last-modified])
|
10
12
|
end
|
11
13
|
|
12
14
|
def fetch(gem_id, type, &block)
|
data/lib/gemstash/gem_pusher.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
require "rubygems/package"
|
3
5
|
require "stringio"
|
4
6
|
|
5
|
-
|
7
|
+
# :nodoc:
|
6
8
|
module Gemstash
|
7
9
|
# Class that supports pushing a new gem to the private repository of gems.
|
8
10
|
class GemPusher
|
@@ -56,9 +58,7 @@ module Gemstash
|
|
56
58
|
resource_exist = storage.resource(full_name).exist?
|
57
59
|
resource_is_indexed = storage.resource(full_name).properties[:indexed] if resource_exist
|
58
60
|
|
59
|
-
if resource_exist && resource_is_indexed
|
60
|
-
raise ExistingVersionError, "Cannot push to an existing version!"
|
61
|
-
end
|
61
|
+
raise ExistingVersionError, "Cannot push to an existing version!" if resource_exist && resource_is_indexed
|
62
62
|
|
63
63
|
storage.resource(full_name).save({ gem: @content }, indexed: true)
|
64
64
|
end
|
@@ -78,6 +78,7 @@ module Gemstash
|
|
78
78
|
existing = Gemstash::DB::Version.find_by_spec(gem_id, spec)
|
79
79
|
raise ExistingVersionError, "Cannot push to an existing version!" if existing && existing.indexed
|
80
80
|
raise YankedVersionError, "Cannot push to a yanked version!" if existing && !existing.indexed
|
81
|
+
|
81
82
|
version_id = Gemstash::DB::Version.insert_by_spec(gem_id, spec)
|
82
83
|
Gemstash::DB::Dependency.insert_by_spec(version_id, spec)
|
83
84
|
end
|
@@ -120,11 +121,12 @@ module Gemstash
|
|
120
121
|
|
121
122
|
def cleanup
|
122
123
|
return unless @tempfile
|
124
|
+
|
123
125
|
@tempfile.close
|
124
126
|
@tempfile.unlink
|
125
127
|
end
|
126
128
|
end
|
127
129
|
|
128
|
-
GemPusher.
|
130
|
+
GemPusher.include LegacyRubyGemsSupport
|
129
131
|
end
|
130
132
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gemstash
|
2
4
|
module GemSource
|
3
5
|
# Module for caching dependencies in a GemSource.
|
@@ -7,9 +9,7 @@ module Gemstash
|
|
7
9
|
def serve_dependencies
|
8
10
|
gems = gems_from_params
|
9
11
|
|
10
|
-
if gems.length > API_REQUEST_LIMIT
|
11
|
-
halt 422, "Too many gems (use --full-index instead)"
|
12
|
-
end
|
12
|
+
halt 422, "Too many gems (use --full-index instead)" if gems.length > API_REQUEST_LIMIT
|
13
13
|
|
14
14
|
content_type "application/octet-stream"
|
15
15
|
Marshal.dump dependencies.fetch(gems)
|
@@ -21,7 +21,7 @@ module Gemstash
|
|
21
21
|
if gems.length > API_REQUEST_LIMIT
|
22
22
|
halt 422, {
|
23
23
|
"error" => "Too many gems (use --full-index instead)",
|
24
|
-
"code"
|
24
|
+
"code" => 422
|
25
25
|
}.to_json
|
26
26
|
end
|
27
27
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
|
3
5
|
module Gemstash
|
@@ -15,6 +17,7 @@ module Gemstash
|
|
15
17
|
def self.matches?(env)
|
16
18
|
rewriter = rack_env_rewriter.for(env)
|
17
19
|
return false unless rewriter.matches?
|
20
|
+
|
18
21
|
rewriter.rewrite
|
19
22
|
true
|
20
23
|
end
|
@@ -44,7 +47,7 @@ module Gemstash
|
|
44
47
|
end
|
45
48
|
|
46
49
|
def serve_versions
|
47
|
-
halt
|
50
|
+
halt 404, "Not yet supported"
|
48
51
|
end
|
49
52
|
|
50
53
|
def serve_info(name)
|
@@ -54,7 +57,7 @@ module Gemstash
|
|
54
57
|
def serve_marshal(id)
|
55
58
|
authorization.protect(self) do
|
56
59
|
auth.check("fetch") if gemstash_env.config[:protected_fetch]
|
57
|
-
gem_full_name = id.
|
60
|
+
gem_full_name = id.delete_suffix(".gemspec.rz")
|
58
61
|
gem = fetch_gem(gem_full_name)
|
59
62
|
halt 404 unless gem.exist?(:spec)
|
60
63
|
content_type "application/octet-stream"
|
@@ -69,7 +72,7 @@ module Gemstash
|
|
69
72
|
def serve_gem(id)
|
70
73
|
authorization.protect(self) do
|
71
74
|
auth.check("fetch") if gemstash_env.config[:protected_fetch]
|
72
|
-
gem_full_name = id.
|
75
|
+
gem_full_name = id.delete_suffix(".gem")
|
73
76
|
gem = fetch_gem(gem_full_name)
|
74
77
|
content_type "application/octet-stream"
|
75
78
|
gem.content(:gem)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
|
3
5
|
module Gemstash
|
@@ -11,6 +13,7 @@ module Gemstash
|
|
11
13
|
def call(env)
|
12
14
|
Gemstash::GemSource.sources.each do |source|
|
13
15
|
next unless source.matches?(env)
|
16
|
+
|
14
17
|
env["gemstash.gem_source"] = source
|
15
18
|
break
|
16
19
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
require "cgi"
|
3
5
|
|
@@ -12,6 +14,7 @@ module Gemstash
|
|
12
14
|
def self.matches?(env)
|
13
15
|
rewriter = rack_env_rewriter.for(env)
|
14
16
|
return false unless rewriter.matches?
|
17
|
+
|
15
18
|
rewriter.rewrite
|
16
19
|
env["gemstash.upstream"] = rewriter.captures["upstream_url"]
|
17
20
|
capture_user_agent(env)
|
@@ -90,8 +93,10 @@ module Gemstash
|
|
90
93
|
private
|
91
94
|
|
92
95
|
def upstream
|
93
|
-
@upstream ||= Gemstash::Upstream.new(
|
94
|
-
|
96
|
+
@upstream ||= Gemstash::Upstream.new(
|
97
|
+
env["gemstash.upstream"],
|
98
|
+
user_agent: env["gemstash.user-agent"]
|
99
|
+
)
|
95
100
|
end
|
96
101
|
|
97
102
|
def index_upstream
|
@@ -135,6 +140,7 @@ module Gemstash
|
|
135
140
|
|
136
141
|
def set_gem_headers(gem, resource_type)
|
137
142
|
return unless gem.property?(:headers, resource_type)
|
143
|
+
|
138
144
|
gem_headers = gem.properties[:headers][resource_type]
|
139
145
|
headers["Content-Type"] = gem_headers["content-type"] if gem_headers.include?("content-type")
|
140
146
|
headers["Last-Modified"] = gem_headers["last-modified"] if gem_headers.include?("last-modified")
|
@@ -192,7 +198,7 @@ module Gemstash
|
|
192
198
|
# default upstream).
|
193
199
|
class RubygemsSource < Gemstash::GemSource::UpstreamSource
|
194
200
|
def self.matches?(env)
|
195
|
-
env["gemstash.upstream"] = if env["HTTP_X_GEMFILE_SOURCE"].to_s.empty?
|
201
|
+
env["gemstash.upstream"] = if env["gemstash.env"].config[:ignore_gemfile_source] || env["HTTP_X_GEMFILE_SOURCE"].to_s.empty?
|
196
202
|
env["gemstash.env"].config[:rubygems_url]
|
197
203
|
else
|
198
204
|
env["HTTP_X_GEMFILE_SOURCE"]
|
data/lib/gemstash/gem_source.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
require "forwardable"
|
3
5
|
|
4
6
|
module Gemstash
|
5
|
-
|
7
|
+
# :nodoc:
|
6
8
|
module GemSource
|
7
9
|
autoload :DependencyCaching, "gemstash/gem_source/dependency_caching"
|
8
10
|
autoload :PrivateSource, "gemstash/gem_source/private_source"
|
@@ -27,7 +29,7 @@ module Gemstash
|
|
27
29
|
include Gemstash::Logging
|
28
30
|
|
29
31
|
def_delegators :@app, :cache_control, :content_type, :env, :halt,
|
30
|
-
|
32
|
+
:headers, :http_client_for, :params, :redirect, :request
|
31
33
|
|
32
34
|
def initialize(app)
|
33
35
|
@app = app
|
data/lib/gemstash/gem_yanker.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
|
3
5
|
module Gemstash
|
@@ -52,9 +54,11 @@ module Gemstash
|
|
52
54
|
def update_database
|
53
55
|
gemstash_env.db.transaction do
|
54
56
|
raise UnknownGemError, "Cannot yank an unknown gem!" unless Gemstash::DB::Rubygem[name: @gem_name]
|
57
|
+
|
55
58
|
version = Gemstash::DB::Version.find_by_full_name(full_name)
|
56
59
|
raise UnknownVersionError, "Cannot yank an unknown version!" unless version
|
57
60
|
raise YankedVersionError, "Cannot yank an already yanked version!" unless version.indexed
|
61
|
+
|
58
62
|
version.deindex
|
59
63
|
storage.resource(version.storage_id).update_properties(indexed: false)
|
60
64
|
end
|
data/lib/gemstash/health.rb
CHANGED
data/lib/gemstash/http_client.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "gemstash"
|
2
4
|
require "faraday"
|
3
5
|
require "faraday_middleware"
|
4
6
|
|
5
7
|
module Gemstash
|
6
|
-
|
8
|
+
# :nodoc:
|
7
9
|
class WebError < StandardError
|
8
10
|
attr_reader :code
|
9
11
|
|
@@ -13,19 +15,19 @@ module Gemstash
|
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
|
-
|
18
|
+
# :nodoc:
|
17
19
|
class ConnectionError < WebError
|
18
20
|
def initialize(message)
|
19
21
|
super(message, 502) # Bad Gateway
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
|
25
|
+
# :nodoc:
|
24
26
|
class HTTPClient
|
25
27
|
extend Gemstash::Env::Helper
|
26
28
|
include Gemstash::Logging
|
27
29
|
|
28
|
-
DEFAULT_USER_AGENT = "Gemstash/#{Gemstash::VERSION}"
|
30
|
+
DEFAULT_USER_AGENT = "Gemstash/#{Gemstash::VERSION}"
|
29
31
|
|
30
32
|
def self.for(upstream)
|
31
33
|
client = Faraday.new(upstream.to_s) do |config|
|
@@ -33,12 +35,17 @@ module Gemstash
|
|
33
35
|
config.adapter :net_http
|
34
36
|
config.options.timeout = gemstash_env.config[:fetch_timeout]
|
35
37
|
end
|
38
|
+
|
39
|
+
client.basic_auth(upstream.user, upstream.password) if upstream.auth?
|
40
|
+
|
36
41
|
user_agent = "#{upstream.user_agent} " unless upstream.user_agent.to_s.empty?
|
37
42
|
user_agent = user_agent.to_s + DEFAULT_USER_AGENT
|
38
43
|
|
39
44
|
new(client, user_agent: user_agent)
|
40
45
|
end
|
41
46
|
|
47
|
+
attr_reader :client
|
48
|
+
|
42
49
|
def initialize(client = nil, user_agent: nil)
|
43
50
|
@client = client
|
44
51
|
@user_agent = user_agent || DEFAULT_USER_AGENT
|
@@ -71,6 +78,7 @@ module Gemstash
|
|
71
78
|
rescue Faraday::ConnectionFailed => e
|
72
79
|
log_error("Connection failure", e)
|
73
80
|
raise(ConnectionError, e.message) unless times > 0
|
81
|
+
|
74
82
|
log.info "retrying... #{times} more times"
|
75
83
|
end
|
76
84
|
end
|
data/lib/gemstash/logging.rb
CHANGED
@@ -1,66 +1 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
@@ -1,66 +1 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
@@ -1,66 +1 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
@@ -1,66 +1 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
@@ -1,66 +1 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
@@ -1,66 +1 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|