Commit c02bcdab authored by Léo-Paul Géneau's avatar Léo-Paul Géneau 👾

Fix undefined rubygems version

Traceback (most recent call last):
  ...
    recipe.install()
  File "rubygemsrecipe/rubygems.py", line 347, in install
    gem_executable):
  File "rubygemsrecipe/rubygems.py", line 300, in get_dependency_list
    if self.version[0] < '3':
TypeError: 'NoneType' object has no attribute '__getitem__'

The test that was added in 60b10788 is adapted due to the call to subprocess.checkout .
parent 60b10788
......@@ -34,6 +34,7 @@ class Recipe(object):
buildout['buildout']['parts-directory'],
self.name,
)
self.bindir = os.path.join(self.options['location'], 'bin')
self.gems = options.get('gems')
if self.gems:
......@@ -42,10 +43,12 @@ class Recipe(object):
raise zc.buildout.UserError(
"Configuration error, 'gems' option is missing")
self.version = options.get('version')
self.url = options.get('url')
# Allow to define specific ruby executable. If not, take just 'ruby'
self.ruby_executable = options.get('ruby-executable', 'ruby')
self.version = self.get_rubygems_version()
if int(self.version.split(".")[0]) < 2:
raise zc.buildout.UserError("Rubygems version must be >= 2.0.0")
deployment = options.get('deployment')
self.deployment = is_true(deployment) if deployment else not allow_picked_versions()
......@@ -172,45 +175,29 @@ class Recipe(object):
gem_dict['version'] = parsed_gem[1].strip()
return gem_dict
def _get_latest_rubygems(self):
if self.url:
version = self.version
if not version:
version = (
re.search(r'rubygems-([0-9.]+).zip$', self.url).group(1)
)
return (self.url, version)
if self.version:
return ('https://rubygems.org/rubygems/'
'rubygems-%s.zip' % self.version, self.version)
def _get_rubygems_url(self, version):
if version:
return 'https://rubygems.org/rubygems/rubygems-%s.zip' % version
f = urllib.request.urlopen('https://rubygems.org/pages/download')
s = f.read().decode('utf-8')
f.close()
r = re.search(r'https://rubygems.org/rubygems/'
r'rubygems-([0-9.]+).zip', s)
r = re.search(r'https://rubygems.org/rubygems/rubygems-([0-9.]+).zip', s)
if r:
url = r.group(0)
version = r.group(1)
return (url, version)
return r.group(0)
else:
raise zc.buildout.UserError(
'Can\'t find latest rubygems version.')
def _install_rubygems(self):
url, version = self._get_latest_rubygems()
if int(version.split(".")[0]) < 2:
raise zc.buildout.UserError("Rubygems version must be >= 2.0.0")
srcdir = os.path.join(self.buildout['buildout']['parts-directory'],
'rubygems-' + version)
'rubygems-' + self.version)
options = {
'url': url,
'url': self.url,
'destination': srcdir,
}
recipe = Download(self.buildout, self.name, options)
recipe.install()
self.version = version
current_dir = os.getcwd()
try:
......@@ -324,15 +311,22 @@ class Recipe(object):
],
} for match in self.gem_regex.findall(cmd_result)]
def get_rubygems_version(self):
gem_executable = self.get_gem_executable(self.bindir)
if gem_executable:
return self.run([gem_executable, '--version',])
if not self.url:
self.url = self._get_rubygems_url(self.options.get('version'))
return re.search(r'rubygems-([0-9.]+).zip$', self.url).group(1)
def install(self):
parts = [self.options['location']]
bindir = os.path.join(self.options['location'], 'bin')
gem_executable = self.get_gem_executable(bindir)
gem_executable = self.get_gem_executable(self.bindir)
if not gem_executable:
self._install_rubygems()
gem_executable = self.get_gem_executable(bindir)
gem_executable = self.get_gem_executable(self.bindir)
gem_dict_list = list(map(self.get_gem_dict, self.gems))
for gem_dict in gem_dict_list:
......@@ -359,11 +353,11 @@ class Recipe(object):
constraint, match[0], gem_dict['gemname'])
self.log.info('installing ruby gem "%s"', gem_dict['gemname'])
self._install_gem(gem_dict, gem_executable, bindir)
self._install_gem(gem_dict, gem_executable, self.bindir)
for executable in os.listdir(bindir):
for executable in os.listdir(self.bindir):
installed_path = self._install_executable(
os.path.join(bindir, executable)
os.path.join(self.bindir, executable)
)
parts.append(installed_path)
......
......@@ -17,6 +17,8 @@ import zc.buildout
import rubygems
RUBYGEMS_DEFAULT_VERSION = '2.0.0'
def touch(path):
with path.open('w') as f:
......@@ -24,9 +26,31 @@ def touch(path):
class fixture(object):
def __init__(self, options=None, version='2.0.0'):
def __init__(self, options=None, version=RUBYGEMS_DEFAULT_VERSION,
rubygems_installed=False):
self.options = options or {}
self.version = version
self.version = self.options.get('return', {}).get('version', version)
self.to_patch = (
('check_output', 'rubygems.subprocess.check_output'),
('urlopen', 'rubygems.urllib.request.urlopen'),
('download', 'rubygems.Download'),
)
self.patch_return_value_dict = {
'urlopen': BytesIO(bytes(
('https://rubygems.org/rubygems/rubygems-%s.zip'
% RUBYGEMS_DEFAULT_VERSION).encode('utf-8')
)),
}
self.to_create = ()
if rubygems_installed:
self.to_patch.append(
('get_version', 'rubygems.Recipe.get_rubygems_version'))
self.patch_return_value_dict['get_version'] = self.version
self.to_create.append(path / 'rubygems/bin/gem')
def __call__(self, func):
@functools.wraps(func)
......@@ -53,24 +77,21 @@ class fixture(object):
def set_up(self):
name = 'rubygems'
version = self.options.get('return', {}).get('version', self.version)
self.patch((
('check_output', 'rubygems.subprocess.check_output'),
('urlopen', 'rubygems.urllib.request.urlopen'),
('download', 'rubygems.Download'),
))
self.patches['urlopen'].return_value = BytesIO(
b'https://rubygems.org/rubygems/rubygems-2.0.0.zip'
)
self.patch(self.to_patch)
for k, v in self.patch_return_value_dict.items():
self.patches[k].return_value = v
self.makedirs((
'bin',
'ruby-' + version,
'rubygems-' + version,
'ruby-' + self.version,
'rubygems-' + self.version,
'rubygems/bin',
))
for file_path in self.to_create:
touch(file_path)
buildout = {'buildout': dict({
'parts-directory': str(self.tempdir),
'bin-directory': str(self.tempdir / 'bin'),
......@@ -78,7 +99,7 @@ class fixture(object):
options = self.options.get('recipe', {})
return buildout, name, options, version
return buildout, name, options, self.version
def tear_down(self):
for patcher in self.patchers.values():
......@@ -108,8 +129,9 @@ class RubyGemsTestCase(unittest.TestCase):
args = patches['download'].mock_calls[0][1]
self.assertEqual(args[2], {
'url': 'https://rubygems.org/rubygems/rubygems-2.0.0.zip',
'destination': str(path / 'rubygems-2.0.0'),
'url': 'https://rubygems.org/rubygems/rubygems-%s.zip'
% RUBYGEMS_DEFAULT_VERSION,
'destination': str(path / ('rubygems-' + RUBYGEMS_DEFAULT_VERSION)),
})
expected_install_arg_list_list.insert(0, [
......@@ -193,13 +215,14 @@ class RubyGemsDefaultTestCase(RubyGemsTestCase):
@fixture({'recipe': {
'gems': 'sass',
'url': 'https://rubygems.org/rubygems/rubygems-2.0.0.zip',
'url': 'https://rubygems.org/rubygems/rubygems-%s.zip'
% RUBYGEMS_DEFAULT_VERSION,
}})
def test_version_from_url(self, path, patches, buildout, name, options, version):
recipe = rubygems.Recipe(buildout, name, options)
recipe.install()
@fixture({'recipe': {'gems': 'sass'}, 'version': '2.0.0'})
@fixture({'recipe': {'gems': 'sass'}, 'version': RUBYGEMS_DEFAULT_VERSION})
def test_version(self, path, patches, buildout, name, options, version):
recipe = rubygems.Recipe(buildout, name, options)
recipe.install()
......@@ -207,10 +230,10 @@ class RubyGemsDefaultTestCase(RubyGemsTestCase):
@fixture({'recipe': {'gems': 'sass'}})
def test_no_version(self, path, patches, buildout, name, options, version):
patches['urlopen'].return_value = BytesIO(b'')
recipe = rubygems.Recipe(buildout, name, options)
self.assertRaisesRegexp(zc.buildout.UserError,
'Can\'t find latest rubygems version.',
recipe.install
rubygems.Recipe,
buildout, name, options
)
@fixture({'recipe': {'gems': 'sass'}})
......@@ -230,10 +253,9 @@ class RubyGemsDefaultTestCase(RubyGemsTestCase):
touch(pathlib.Path(recipe.options['location']) / 'bin/sass')
recipe.install()
@fixture({'recipe': {'gems': 'sass==1.0'}})
@fixture({'recipe': {'gems': 'sass==1.0'}, 'rubygems_installed': True})
def test_pinned_versions(self, path, patches, buildout, name, options, version):
recipe = rubygems.Recipe(buildout, name, options)
touch(path / 'rubygems/bin/gem')
recipe.install()
args = patches['check_output'].mock_calls[0][1]
......@@ -302,10 +324,12 @@ class RubyGemsDeploymentTestCase(RubyGemsTestCase):
self.install_with_default_rubygems_test(
path, patches, expected_install_arg_list_list)
@deployment_fixture({'recipe': {'gems': 'hashie==0.3.1'}})
@deployment_fixture({
'recipe': {'gems': 'hashie==0.3.1'},
'rubygems_installed': True
})
def test_already_installed_rubygems(
self, path, patches, buildout, name, options, version):
touch(path / 'rubygems/bin/gem')
self.deployment_install_test(
buildout, name, path, patches, options, version)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment