puppet-forge-server 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +20 -0
- data/Gemfile +20 -0
- data/README.md +127 -0
- data/bin/puppet-forge-server +21 -0
- data/lib/puppet_forge_server.rb +63 -0
- data/lib/puppet_forge_server/api/v1/modules.rb +71 -0
- data/lib/puppet_forge_server/api/v1/releases.rb +31 -0
- data/lib/puppet_forge_server/api/v3/modules.rb +57 -0
- data/lib/puppet_forge_server/api/v3/releases.rb +38 -0
- data/lib/puppet_forge_server/app/version1.rb +67 -0
- data/lib/puppet_forge_server/app/version3.rb +68 -0
- data/lib/puppet_forge_server/backends/directory.rb +67 -0
- data/lib/puppet_forge_server/backends/proxy.rb +63 -0
- data/lib/puppet_forge_server/backends/proxy_v1.rb +69 -0
- data/lib/puppet_forge_server/backends/proxy_v3.rb +63 -0
- data/lib/puppet_forge_server/errors.rb +20 -0
- data/lib/puppet_forge_server/http/http_client.rb +35 -0
- data/lib/puppet_forge_server/models/builder.rb +37 -0
- data/lib/puppet_forge_server/models/metadata.rb +46 -0
- data/lib/puppet_forge_server/patches.rb +61 -0
- data/lib/puppet_forge_server/server.rb +88 -0
- data/lib/puppet_forge_server/utils/archiver.rb +29 -0
- data/lib/puppet_forge_server/utils/buffer.rb +33 -0
- data/lib/puppet_forge_server/utils/http.rb +30 -0
- data/lib/puppet_forge_server/utils/option_parser.rb +76 -0
- data/lib/puppet_forge_server/utils/url.rb +36 -0
- data/lib/puppet_forge_server/version.rb +19 -0
- data/puppet-forge-server.gemspec +47 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 50dd26198a713585d3ff7bc041d02c6d51f3db2c
|
4
|
+
data.tar.gz: 6d2c8cdda16ba2f5fcd003b93d455737b49d89c4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f1231fe9ecb57b1f9a478a4d9b3ed951a6b8c6887728600278a338841ce56fca69dae6a1736251811c7fa5dc4dcc966ca5d45aeb956639c95a533817351140a
|
7
|
+
data.tar.gz: 99947b8750cfc37c4e58da45fc68e51d44de742b67e36da7aa4e111d58984871fc7560092ad1822f7e0923eeda5074bcbaca154837b09bf33c180007b09a68c4
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.sw[op]
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
.yardoc
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.rake_t_cache
|
19
|
+
/Gemfile.lock
|
20
|
+
/.idea
|
21
|
+
/*.iml
|
data/.travis.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright 2014 North Development AB
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
language: ruby
|
18
|
+
rvm:
|
19
|
+
- 1.9.3
|
20
|
+
- 2.0.0
|
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright 2014 North Development AB
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
source 'https://rubygems.org'
|
19
|
+
|
20
|
+
gemspec
|
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# Puppet Forge Server
|
2
|
+
|
3
|
+
Private Puppet Forge Server supporting local files and both v1 and v3 API proxies. Heavily inspired by the [Puppet Library](https://github.com/drrb/puppet-library).
|
4
|
+
|
5
|
+
[![Build Status](https://api.travis-ci.org/unibet/puppet-forge-server.svg)](https://travis-ci.org/unibet/puppet-forge-server)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/puppet-forge-server.svg)](http://badge.fury.io/rb/puppet-forge-server)
|
7
|
+
|
8
|
+
Puppet Forge Server provides approximated implementation of both [v1](https://projects.puppetlabs.com/projects/module-site/wiki/Server-api)
|
9
|
+
and [v3](https://forgeapi.puppetlabs.com/) APIs, but behavioral deviations from the official implementation might occur.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Install the gem
|
14
|
+
```
|
15
|
+
gem install puppet-forge-server
|
16
|
+
puppet-forge-server --help
|
17
|
+
```
|
18
|
+
or get the latest source
|
19
|
+
```
|
20
|
+
git clone https://github.com/unibet/puppet-forge-server
|
21
|
+
cd puppet-forge-server
|
22
|
+
bundle install
|
23
|
+
bundle exec bin/puppet-forge-server --help
|
24
|
+
```
|
25
|
+
|
26
|
+
## Getting Started
|
27
|
+
|
28
|
+
### Proxy
|
29
|
+
|
30
|
+
#### Proxy the official Puppet Forge v3 API
|
31
|
+
Just start the server providing the forge URL
|
32
|
+
```
|
33
|
+
bundle exec bin/puppet-forge-server -x https://forgeapi.puppetlabs.com
|
34
|
+
```
|
35
|
+
|
36
|
+
Run puppet module install to test it
|
37
|
+
```
|
38
|
+
puppet module install --module_repository=http://localhost:8080 puppetlabs-stdlib
|
39
|
+
```
|
40
|
+
|
41
|
+
#### Proxy the official Puppet Forge v1 API and local Pulp puppet repository
|
42
|
+
Just start the server providing forge and local pulp URLs
|
43
|
+
```
|
44
|
+
bundle exec bin/puppet-forge-server -x http://forge.puppetlabs.com -x http://my.local.pulp/pulp_puppet/forge/repository/demo
|
45
|
+
```
|
46
|
+
|
47
|
+
Run puppet module install to test it. Please note that depending on your internet connection and puppet version it might take a while for the first call to get executed.
|
48
|
+
v3 API requires checksuming the files, which means all involved module files will be cached.
|
49
|
+
```
|
50
|
+
puppet module install --module_repository=http://localhost:8080 puppetlabs-stdlib
|
51
|
+
```
|
52
|
+
|
53
|
+
### Locally stored modules
|
54
|
+
|
55
|
+
Download given modules from the official forge and start the server pointing into directory with module files
|
56
|
+
```
|
57
|
+
mkdir modules
|
58
|
+
wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-apache-0.9.0.tar.gz
|
59
|
+
wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-concat-1.0.0.tar.gz
|
60
|
+
wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-stdlib-2.4.0.tar.gz
|
61
|
+
bundle exec bin/puppet-forge-server -m modules/
|
62
|
+
```
|
63
|
+
|
64
|
+
Run puppet module install to test it
|
65
|
+
```
|
66
|
+
puppet module install --module_repository=http://localhost:8080 puppetlabs-stdlib
|
67
|
+
```
|
68
|
+
|
69
|
+
### All-in
|
70
|
+
|
71
|
+
Download given modules from the official forge and start the server pointing into directory with module files and proxy URLs
|
72
|
+
```
|
73
|
+
mkdir modules
|
74
|
+
wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-apache-0.9.0.tar.gz
|
75
|
+
wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-concat-1.0.0.tar.gz
|
76
|
+
wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-stdlib-2.4.0.tar.gz
|
77
|
+
bundle exec bin/puppet-forge-server -m modules/ -x https://forgeapi.puppetlabs.com -x http://my.local.pulp/pulp_puppet/forge/repository/demo
|
78
|
+
```
|
79
|
+
|
80
|
+
Create an example Puppetfile
|
81
|
+
```
|
82
|
+
cat > Puppetfile <<EOF
|
83
|
+
forge 'http://localhost:8080'
|
84
|
+
|
85
|
+
mod 'puppetlabs/apache'
|
86
|
+
EOF
|
87
|
+
```
|
88
|
+
|
89
|
+
Run librarian-puppet with *--no-use-v1-api* option to instruct it to use v3 API
|
90
|
+
```
|
91
|
+
librarian-puppet install --no-use-v1-api
|
92
|
+
```
|
93
|
+
## Architecture
|
94
|
+
|
95
|
+
Code is structured with MVC in mind to allow easier maintenance and readability
|
96
|
+
|
97
|
+
### API (view)
|
98
|
+
|
99
|
+
*API* classes (actually modules only) are used to extend [Sinatra](http://www.sinatrarb.com/) application classes.
|
100
|
+
Every module corresponds to official API endpoint and used to present received model data in fasion required by the given API version.
|
101
|
+
|
102
|
+
### App (controller)
|
103
|
+
|
104
|
+
Every *App* class is a [Sinatra](http://www.sinatrarb.com/) application class and is responsible for mapping API endpoints, querying backends for requested data and providing the results using API (view) modules.
|
105
|
+
|
106
|
+
### Models
|
107
|
+
|
108
|
+
Puppet module *metadata* json representation is used as a main business *model*.
|
109
|
+
|
110
|
+
### Backends
|
111
|
+
|
112
|
+
*Backend* classes are providing the means of fetching required data and creating model instances.
|
113
|
+
|
114
|
+
|
115
|
+
## TODO
|
116
|
+
|
117
|
+
1. Create UTs for core logic
|
118
|
+
2. Implement *source* and *git* backends to match [puppet library](https://github.com/drrb/puppet-library) feature set
|
119
|
+
|
120
|
+
## License
|
121
|
+
|
122
|
+
[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
|
123
|
+
|
124
|
+
## Reference
|
125
|
+
|
126
|
+
* [Puppet Library](https://github.com/drrb/puppet-library)
|
127
|
+
* [Puppet Anvil](https://github.com/jhaals/puppet-anvil)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright 2014 North Development AB
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
18
|
+
|
19
|
+
require 'puppet_forge_server'
|
20
|
+
|
21
|
+
PuppetForgeServer::Server.new.go(ARGV)
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright 2014 North Development AB
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
require 'puppet_forge_server/patches'
|
18
|
+
require 'puppet_forge_server/version'
|
19
|
+
|
20
|
+
module PuppetForgeServer
|
21
|
+
autoload :Server, 'puppet_forge_server/server'
|
22
|
+
autoload :Errors, 'puppet_forge_server/errors'
|
23
|
+
|
24
|
+
module Api
|
25
|
+
module V1
|
26
|
+
autoload :Modules, 'puppet_forge_server/api/v1/modules'
|
27
|
+
autoload :Releases, 'puppet_forge_server/api/v1/releases'
|
28
|
+
end
|
29
|
+
module V3
|
30
|
+
autoload :Modules, 'puppet_forge_server/api/v3/modules'
|
31
|
+
autoload :Releases, 'puppet_forge_server/api/v3/releases'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module App
|
36
|
+
autoload :Version1, 'puppet_forge_server/app/version1'
|
37
|
+
autoload :Version3, 'puppet_forge_server/app/version3'
|
38
|
+
end
|
39
|
+
|
40
|
+
module Backends
|
41
|
+
autoload :Directory, 'puppet_forge_server/backends/directory'
|
42
|
+
autoload :Proxy, 'puppet_forge_server/backends/proxy'
|
43
|
+
autoload :ProxyV1, 'puppet_forge_server/backends/proxy_v1'
|
44
|
+
autoload :ProxyV3, 'puppet_forge_server/backends/proxy_v3'
|
45
|
+
end
|
46
|
+
|
47
|
+
module Models
|
48
|
+
autoload :Builder, 'puppet_forge_server/models/builder'
|
49
|
+
autoload :Metadata, 'puppet_forge_server/models/metadata'
|
50
|
+
end
|
51
|
+
|
52
|
+
module Utils
|
53
|
+
autoload :Archiver, 'puppet_forge_server/utils/archiver'
|
54
|
+
autoload :OptionParser, 'puppet_forge_server/utils/option_parser'
|
55
|
+
autoload :Url, 'puppet_forge_server/utils/url'
|
56
|
+
autoload :Buffer, 'puppet_forge_server/utils/buffer'
|
57
|
+
autoload :Http, 'puppet_forge_server/utils/http'
|
58
|
+
end
|
59
|
+
|
60
|
+
module Http
|
61
|
+
autoload :HttpClient, 'puppet_forge_server/http/http_client'
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright 2014 drrb
|
4
|
+
# Copyright 2014 North Development AB
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
module PuppetForgeServer::Api::V1
|
19
|
+
module Modules
|
20
|
+
|
21
|
+
def get_modules(metadata)
|
22
|
+
modules = metadata.map do |element|
|
23
|
+
name = element[:metadata].name.sub(/^[^-]+-/, '')
|
24
|
+
full_name = element[:metadata].name.sub('-', '/')
|
25
|
+
{
|
26
|
+
:author => element[:metadata].author,
|
27
|
+
:full_name => full_name,
|
28
|
+
:name => name,
|
29
|
+
:desc => element[:metadata].description,
|
30
|
+
:version => element[:metadata].version,
|
31
|
+
:project_url => element[:metadata].project_page,
|
32
|
+
:releases => [{:version => element[:metadata].version}],
|
33
|
+
:tag_list => [element[:metadata].author, name]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
merge_modules(modules)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def merge_modules(modules)
|
42
|
+
grouped_modules = modules.group_by do |result|
|
43
|
+
result[:full_name]
|
44
|
+
end
|
45
|
+
|
46
|
+
grouped_modules.values.map do |value|
|
47
|
+
merge_values(value)
|
48
|
+
end.flatten.uniq
|
49
|
+
end
|
50
|
+
|
51
|
+
def merge_values(value)
|
52
|
+
highest_version, tags, releases = value.inject([nil, [], []]) do |(highest_version, tags, releases), result|
|
53
|
+
[
|
54
|
+
max_version(highest_version, result[:version]),
|
55
|
+
tags + (result[:tag_list] || []),
|
56
|
+
releases + (result[:releases] || [])
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
value.first.tap do |result|
|
61
|
+
result[:version] = highest_version
|
62
|
+
result[:tag_list] = tags.uniq
|
63
|
+
result[:releases] = releases.uniq.version_sort_by { |r| r[:version] }.reverse
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def max_version(left, right)
|
68
|
+
[Gem::Version.new(left), Gem::Version.new(right)].max.version
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright 2014 North Development AB
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module PuppetForgeServer::Api::V1
|
18
|
+
module Releases
|
19
|
+
def get_releases(metadata)
|
20
|
+
metadata.map do |element|
|
21
|
+
{
|
22
|
+
:file => "/api/v1/files#{element[:path]}",
|
23
|
+
:version => element[:metadata].version,
|
24
|
+
:dependencies => element[:metadata].dependencies.map do |dependency|
|
25
|
+
[dependency['name'], dependency['version_requirement']]
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end.version_sort_by { |r| r[:version] }.reverse
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright 2014 North Development AB
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module PuppetForgeServer::Api::V3
|
18
|
+
module Modules
|
19
|
+
include PuppetForgeServer::Api::V3::Releases
|
20
|
+
|
21
|
+
def get_modules(metadata)
|
22
|
+
modules = {}
|
23
|
+
metadata.each do |element|
|
24
|
+
if modules[element[:metadata].name]
|
25
|
+
if max_version(modules[element[:metadata].name][:current_release][:version], element[:metadata].version) == element[:metadata].version
|
26
|
+
tags = modules[element[:metadata].name][:current_release][:tags]
|
27
|
+
modules[element[:metadata].name][:current_release] = get_releases([element]).first
|
28
|
+
modules[element[:metadata].name][:current_release][:tags] = (modules[element[:metadata].name][:current_release][:tags] + tags).uniq
|
29
|
+
end
|
30
|
+
modules[element[:metadata].name][:releases] = (modules[element[:metadata].name][:releases] + releases_version(element[:metadata])).version_sort_by { |r| r[:version] }.reverse
|
31
|
+
else
|
32
|
+
name = element[:metadata].name.sub(/^[^-]+-/, '')
|
33
|
+
modules[element[:metadata].name] = {
|
34
|
+
:uri => "/v3/modules/#{element[:metadata].name}",
|
35
|
+
:name => name,
|
36
|
+
:homepage_url => element[:metadata].project_page,
|
37
|
+
:issues_url => element[:metadata].issues_url,
|
38
|
+
:releases => releases_version(element[:metadata]),
|
39
|
+
:current_release => get_releases([element]).first
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
STDERR.puts 'WARNING: Requested module count is more than 1' unless modules.values.count == 1
|
45
|
+
modules.values.first
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def releases_version(metadata)
|
50
|
+
[{:version => metadata.version, :uri => "/v3/releases/#{metadata.name}-#{metadata.version}"}]
|
51
|
+
end
|
52
|
+
|
53
|
+
def max_version(left, right)
|
54
|
+
[Gem::Version.new(left), Gem::Version.new(right)].max.version
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|