Merge #88 Resolve HEAD in ksurl to actual hash
This commit is contained in:
commit
81e90eb780
@ -507,7 +507,8 @@ Image Build Settings
|
||||
|
||||
.. note::
|
||||
Config can contain anything what is accepted by
|
||||
koji image-build --config configfile.ini
|
||||
``koji image-build --config configfile.ini``
|
||||
|
||||
Repo is currently the only option which is being automatically transformed
|
||||
into a string.
|
||||
|
||||
@ -515,6 +516,10 @@ Image Build Settings
|
||||
The 'format' attr is [('image_type', 'image_suffix'), ...].
|
||||
productmd should ideally contain all of image types and suffixes.
|
||||
|
||||
If ``ksurl`` ends with ``#HEAD``, Pungi will figure out the SHA1 hash of
|
||||
current HEAD and use that instead.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
::
|
||||
@ -528,6 +533,7 @@ Example
|
||||
'target': 'koji-target-name',
|
||||
'ksversion': 'F23', # value from pykickstart
|
||||
'version': '23',
|
||||
# correct SHA1 hash will be put into the URL below automatically
|
||||
'ksurl': 'https://git.fedorahosted.org/git/spin-kickstarts.git?somedirectoryifany#HEAD',
|
||||
'kickstart': "fedora-docker-base.ks",
|
||||
'repo': ["http://someextrarepos.org/repo", "ftp://rekcod.oi/repo].
|
||||
|
@ -4,7 +4,7 @@
|
||||
import os
|
||||
import time
|
||||
|
||||
from pungi.util import get_arch_variant_data
|
||||
from pungi.util import get_arch_variant_data, resolve_git_url
|
||||
from pungi.phases.base import PhaseBase
|
||||
from pungi.linker import Linker
|
||||
from pungi.paths import translate_path
|
||||
@ -34,6 +34,9 @@ class ImageBuildPhase(PhaseBase):
|
||||
for variant in self.compose.get_variants(arch=arch):
|
||||
image_build_data = get_arch_variant_data(self.compose.conf, self.name, arch, variant)
|
||||
for image_conf in image_build_data:
|
||||
# Replace possible ambiguous ref name with explicit hash.
|
||||
if 'ksurl' in image_conf:
|
||||
image_conf['ksurl'] = resolve_git_url(image_conf['ksurl'])
|
||||
image_conf["arches"] = arch # passed to get_image_build_cmd as dict
|
||||
image_conf["variant"] = variant # ^
|
||||
image_conf["install_tree"] = translate_path(self.compose, self.compose.paths.compose.os_tree(arch, variant)) # ^
|
||||
|
@ -23,6 +23,7 @@ import hashlib
|
||||
import errno
|
||||
import pipes
|
||||
import re
|
||||
import urlparse
|
||||
|
||||
from kobo.shortcuts import run
|
||||
from productmd.common import get_major_version
|
||||
@ -214,6 +215,32 @@ def get_arch_variant_data(conf, var_name, arch, variant):
|
||||
return result
|
||||
|
||||
|
||||
def resolve_git_url(url):
|
||||
"""Given a url to a Git repo specifying HEAD as a ref, replace that
|
||||
specifier with actual SHA1 of the commit.
|
||||
|
||||
Otherwise, the original URL will be returned.
|
||||
|
||||
Raises RuntimeError if there was an error. Most likely cause is failure to
|
||||
run git command.
|
||||
"""
|
||||
r = urlparse.urlsplit(url)
|
||||
if r.fragment != 'HEAD':
|
||||
return url
|
||||
|
||||
baseurl = urlparse.urlunsplit((r.scheme, r.netloc, r.path, '', ''))
|
||||
_, output = run(['git', 'ls-remote', baseurl, r.fragment])
|
||||
|
||||
lines = [line for line in output.split('\n') if line]
|
||||
if len(lines) != 1:
|
||||
# This should never happen. HEAD can not match multiple commits in a
|
||||
# single repo, and there can not be a repo without a HEAD.
|
||||
raise RuntimeError('Failed to resolve %s', url)
|
||||
|
||||
fragment = lines[0].split()[0]
|
||||
return urlparse.urlunsplit((r.scheme, r.netloc, r.path, r.query, fragment))
|
||||
|
||||
|
||||
# fomat: {arch|*: [data]}
|
||||
def get_arch_data(conf, var_name, arch):
|
||||
result = []
|
||||
|
50
tests/test_util.py
Executable file
50
tests/test_util.py
Executable file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import mock
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
from pungi import util
|
||||
|
||||
|
||||
class TestGitRefResolver(unittest.TestCase):
|
||||
|
||||
@mock.patch('pungi.util.run')
|
||||
def test_successful_resolve(self, run):
|
||||
run.return_value = (0, 'CAFEBABE\tHEAD\n')
|
||||
|
||||
url = util.resolve_git_url('https://git.example.com/repo.git?somedir#HEAD')
|
||||
|
||||
self.assertEqual(url, 'https://git.example.com/repo.git?somedir#CAFEBABE')
|
||||
run.assert_called_once_with(['git', 'ls-remote', 'https://git.example.com/repo.git', 'HEAD'])
|
||||
|
||||
@mock.patch('pungi.util.run')
|
||||
def test_resolve_missing_spec(self, run):
|
||||
url = util.resolve_git_url('https://git.example.com/repo.git')
|
||||
|
||||
self.assertEqual(url, 'https://git.example.com/repo.git')
|
||||
self.assertEqual(run.mock_calls, [])
|
||||
|
||||
@mock.patch('pungi.util.run')
|
||||
def test_resolve_non_head_spec(self, run):
|
||||
url = util.resolve_git_url('https://git.example.com/repo.git#some-tag')
|
||||
|
||||
self.assertEqual(url, 'https://git.example.com/repo.git#some-tag')
|
||||
self.assertEqual(run.mock_calls, [])
|
||||
|
||||
@mock.patch('pungi.util.run')
|
||||
def test_resolve_ambiguous(self, run):
|
||||
run.return_value = (0, 'CAFEBABE\tF11\nDEADBEEF\tF10\n')
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
util.resolve_git_url('https://git.example.com/repo.git?somedir#HEAD')
|
||||
|
||||
run.assert_called_once_with(['git', 'ls-remote', 'https://git.example.com/repo.git', 'HEAD'])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user