From 59325192e6e7cbf31855542b77e637d14f1c6d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignas=20Kaziuk=C4=97nas?= Date: Mon, 5 Jun 2023 23:45:00 +0300 Subject: [PATCH] [pkg_deb] Fix multiline fields in changes file (#691) * fix multiline fields in changes files * multiline is an enum now --- pkg/private/deb/make_deb.py | 40 ++++++++++++++++++++++----------- tests/deb/control_field_test.py | 16 +++++++++---- tests/deb/pkg_deb_test.py | 26 +++++++++++++++++++++ 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/pkg/private/deb/make_deb.py b/pkg/private/deb/make_deb.py index 9e2e5c5e..b1700825 100644 --- a/pkg/private/deb/make_deb.py +++ b/pkg/private/deb/make_deb.py @@ -14,6 +14,7 @@ """A simple cross-platform helper to create a debian package.""" import argparse +from enum import Enum import gzip import hashlib import io @@ -30,6 +31,8 @@ from pkg.private import helpers +Multiline = Enum('Multiline', ['NO', 'YES', 'YES_ADD_NEWLINE']) + # list of debian fields : (name, mandatory, is_multiline[, default]) # see http://www.debian.org/doc/debian-policy/ch-controlfields.html @@ -118,7 +121,7 @@ def AddArFileEntry(fileobj, filename, fileobj.write(b'\n') # 2-byte alignment padding -def MakeDebianControlField(name: str, value: str, is_multiline:bool=False) -> str: +def MakeDebianControlField(name: str, value: str, multiline:Multiline=Multiline.NO) -> str: """Add a field to a debian control file. https://www.debian.org/doc/debian-policy/ch-controlfields.html#syntax-of-control-files @@ -132,15 +135,20 @@ def MakeDebianControlField(name: str, value: str, is_multiline:bool=False) -> st if isinstance(value, list): value = u', '.join(value) value = value.rstrip() - if not is_multiline: + if multiline == Multiline.NO: value = value.strip() if '\n' in value: raise ValueError( '\\n is not allowed in simple control fields (%s)' % value) lines = value.split('\n') - result = name + ': ' +lines[0].strip() + '\n' - for line in lines[1:]: + i = 0 + if multiline != Multiline.YES_ADD_NEWLINE: + result = name + ': ' + lines[i].strip() + '\n' + i = 1 + else: + result = name + ':\n' + for line in lines[i:]: if not line.startswith(' '): result += ' ' result += line @@ -155,10 +163,10 @@ def CreateDebControl(extrafiles=None, **kwargs): for values in DEBIAN_FIELDS: fieldname = values[0] mandatory = values[1] - is_multiline = values[2] + multiline = Multiline.YES if values[2] else Multiline.NO key = fieldname[0].lower() + fieldname[1:].replace('-', '') if mandatory or (key in kwargs and kwargs[key]): - controlfile += MakeDebianControlField(fieldname, kwargs[key], is_multiline) + controlfile += MakeDebianControlField(fieldname, kwargs[key], multiline) # Create the control.tar file tar = io.BytesIO() with gzip.GzipFile('control.tar.gz', mode='w', fileobj=tar, mtime=0) as gz: @@ -290,21 +298,27 @@ def CreateChanges(output, MakeDebianControlField('Maintainer', maintainer), MakeDebianControlField('Changed-By', maintainer), # The description in the changes file is strange - 'Description:\n %s - %s\n' % (package, description.split('\n')[0]), + MakeDebianControlField('Description', ( + '%s - %s\n') % ( + package, description.split('\n')[0]), + multiline=Multiline.YES_ADD_NEWLINE), MakeDebianControlField('Changes', ( - '\n %s (%s) %s; urgency=%s' + '%s (%s) %s; urgency=%s' '\n Changes are tracked in revision control.') % ( package, version, distribution, urgency), - is_multiline=True), + multiline=Multiline.YES_ADD_NEWLINE), MakeDebianControlField( - 'Files', '\n ' + ' '.join( - [checksums['md5'], debsize, section, priority, deb_basename])), + 'Files', ' '.join( + [checksums['md5'], debsize, section, priority, deb_basename]), + multiline=Multiline.YES_ADD_NEWLINE), MakeDebianControlField( 'Checksums-Sha1', - '\n ' + ' '.join([checksums['sha1'], debsize, deb_basename])), + ' '.join([checksums['sha1'], debsize, deb_basename]), + multiline=Multiline.YES_ADD_NEWLINE), MakeDebianControlField( 'Checksums-Sha256', - '\n ' + ' '.join([checksums['sha256'], debsize, deb_basename])) + ' '.join([checksums['sha256'], debsize, deb_basename]), + multiline=Multiline.YES_ADD_NEWLINE) ]) with open(output, 'wb') as changes_fh: changes_fh.write(changesdata.encode('utf-8')) diff --git a/tests/deb/control_field_test.py b/tests/deb/control_field_test.py index a469141e..5f4f5e94 100644 --- a/tests/deb/control_field_test.py +++ b/tests/deb/control_field_test.py @@ -52,23 +52,31 @@ def test_multiline(self): self.assertEqual( 'Description: fizzbuzz\n', make_deb.MakeDebianControlField( - 'Description', 'fizzbuzz', is_multiline=True)) + 'Description', 'fizzbuzz', multiline=make_deb.Multiline.YES)) self.assertEqual( 'Description: fizz\n buzz\n', make_deb.MakeDebianControlField( - 'Description', 'fizz\n buzz\n', is_multiline=True)) + 'Description', 'fizz\n buzz\n', multiline=make_deb.Multiline.YES)) + self.assertEqual( + 'Description:\n fizz\n buzz\n', + make_deb.MakeDebianControlField( + 'Description', ' fizz\n buzz\n', multiline=make_deb.Multiline.YES_ADD_NEWLINE)) def test_multiline_add_required_space(self): self.assertEqual( 'Description: fizz\n buzz\n', make_deb.MakeDebianControlField( - 'Description', 'fizz\nbuzz', is_multiline=True)) + 'Description', 'fizz\nbuzz', multiline=make_deb.Multiline.YES)) + self.assertEqual( + 'Description:\n fizz\n buzz\n', + make_deb.MakeDebianControlField( + 'Description', 'fizz\nbuzz\n', multiline=make_deb.Multiline.YES_ADD_NEWLINE)) def test_multiline_add_trailing_newline(self): self.assertEqual( 'Description: fizz\n buzz\n baz\n', make_deb.MakeDebianControlField( - 'Description', 'fizz\n buzz\n baz', is_multiline=True)) + 'Description', 'fizz\n buzz\n baz', multiline=make_deb.Multiline.YES)) if __name__ == '__main__': diff --git a/tests/deb/pkg_deb_test.py b/tests/deb/pkg_deb_test.py index 9ef4ac77..285a9655 100644 --- a/tests/deb/pkg_deb_test.py +++ b/tests/deb/pkg_deb_test.py @@ -249,6 +249,32 @@ def test_changes(self): content[d_start + len(d_expect)].isupper(), 'Description has unexpected characters at end (%s)' % content) + self.maxDiff = None + expect = '''Format: 1\.8 +Date: Thu Jan 1 \d{2}:00:00 1970 +Source: fizzbuzz +Binary: fizzbuzz +Architecture: all +Version: 4\.5\.6 +Distribution: trusty +Urgency: low +Maintainer: soméone@somewhere.com +Changed-By: soméone@somewhere.com +Description: + fizzbuzz - toto ®, Й, ק ,م, ๗, あ, 叶, 葉, 말, ü and é +Changes: + fizzbuzz \(4\.5\.6\) trusty; urgency=low + Changes are tracked in revision control\. +Files: + [a-f0-9]{32} \d{4} contrib/devel optional fizzbuzz_4\.5\.6_all\.deb +Checksums-Sha1: + [a-f0-9]{40} \d{4} fizzbuzz_4\.5\.6_all\.deb +Checksums-Sha256: + [a-f0-9]{64} \d{4} fizzbuzz_4\.5\.6_all\.deb +''' + + self.assertRegex(content, expect) + if __name__ == '__main__': unittest.main()