From c0c73b9f429c79aa844e70b265dbff39b9802678 Mon Sep 17 00:00:00 2001 From: Lubomír Sedlář Date: May 09 2018 07:11:37 +0000 Subject: Detect lookaside hash from sources file If the configuration says to use MD5, try to see what is in the sources file and use that. Only if that fails fall back to MD5. If the config already says something else, use that. This will allow deployments that are migrating to new checksum to use it only for some packages. The question is how to actually force the migration. Assuming a package that currently has MD5 sources, one would have to delete the sources file and upload new ones with client configured to use SHA512. That is not a very obvious process. Signed-off-by: Lubomír Sedlář --- diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py index 9b37829..1ac5368 100644 --- a/pyrpkg/cli.py +++ b/pyrpkg/cli.py @@ -29,7 +29,7 @@ import koji_cli.lib import pyrpkg.utils as utils import six -from pyrpkg import rpkgError, log as rpkgLogger +from pyrpkg import rpkgError, log as rpkgLogger, sources from six.moves import configparser @@ -234,6 +234,15 @@ class cliClient(object): raise rpkgError('Missing kojiconfig and kojiprofile to load Koji ' 'session. One of them must be specified.') + # If lookaside hash is configured to md5, check what the sources are + # using and use that. We don't allow downgrades, so if config says + # SHA512, then that's it no matter what's in sources. + if items['lookasidehash'] == 'md5': + items['lookasidehash'] = ( + sources.detect_checksum(os.path.join(self.args.path, 'sources')) + or items['lookasidehash'] + ) + # Create the cmd object self._cmd = self.site.Commands(self.args.path, items['lookaside'], diff --git a/pyrpkg/sources.py b/pyrpkg/sources.py index a443f38..7550edb 100644 --- a/pyrpkg/sources.py +++ b/pyrpkg/sources.py @@ -26,6 +26,22 @@ LINE_PATTERN = re.compile( r'^(?P[^ ]+?) \((?P[^ )]+?)\) = (?P[^ ]+?)$') +def detect_checksum(sourcesfile): + """Open the sources file and try to guess what hash is used in the + lookaside. We already assume that there will only be one type in the + file. If there is no content or the file does not exist (or does not + contain valid lines), ``None`` is returned. + """ + for entry_type in ('old', 'bsd'): + try: + sf = SourcesFile(sourcesfile, entry_type=entry_type) + except MalformedLineError: + continue + if sf.entries: + return sf.entries[0].hashtype + return None + + class SourcesFile(object): def __init__(self, sourcesfile, entry_type, replace=False): self.sourcesfile = sourcesfile diff --git a/tests/test_sources.py b/tests/test_sources.py index fafbaf9..989dd09 100644 --- a/tests/test_sources.py +++ b/tests/test_sources.py @@ -6,6 +6,33 @@ import unittest from pyrpkg import sources +class DetectChecksumTestCase(unittest.TestCase): + def setUp(self): + _, self.sf = tempfile.mkstemp(prefix='rpkg-tests.') + + def tearDown(self): + os.remove(self.sf) + + def _prepare(self, content): + with open(self.sf, 'w') as f: + f.write('%s\n' % content) + + def test_old_file_md5(self): + self._prepare('742d40dc3070297518051c153fabb7f1 foo.tar.bz2') + self.assertEqual(sources.detect_checksum(self.sf), 'md5') + + def test_bsd_file_sha512(self): + self._prepare('SHA512 (foo.tar.bz2) = %s' % ('a' * 128)) + self.assertEqual(sources.detect_checksum(self.sf), 'sha512') + + def test_non_existing_file(self): + self.assertEqual(sources.detect_checksum('/nothing/here'), None) + + def test_malformed_file(self): + self._prepare('Hello world') + self.assertEqual(sources.detect_checksum(self.sf), None) + + class SourceFileEntryTestCase(unittest.TestCase): def test_entry(self): e = sources.SourceFileEntry('md5', 'afile', 'ahash')