Merge lp:~gz/bzr-builddeb/merge_changelog_invalid_version_893495 into lp:bzr-builddeb

Proposed by Martin Packman
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: 663
Merged at revision: 661
Proposed branch: lp:~gz/bzr-builddeb/merge_changelog_invalid_version_893495
Merge into: lp:bzr-builddeb
Diff against target: 102 lines (+46/-8)
2 files modified
merge_changelog.py (+10/-1)
tests/test_merge_changelog.py (+36/-7)
To merge this branch: bzr merge lp:~gz/bzr-builddeb/merge_changelog_invalid_version_893495
Reviewer Review Type Date Requested Status
Jelmer Vernooij code Approve
Review via email: mp+85572@code.launchpad.net

Description of the change

Handle dpkg-mergechangelogs aborting by falling back to other merge hooks rather than thinking it's a successful merge resulting in a zero byte file. This can be hit with invalid versions in one of the changelogs, and newer dpkg versions have become stricter on this front.

Also resolved some bad encoding handling while there, as it was part of the original bug report and gets in the way of one of the neater way of testing (non-ascii versions are rejected in my older dpkg version as well).

The test is written in such a way as it should keep passing if my dpkg patch is accepted and the merge starts succeeding it will continue to pass, regardless of the version installed. That's the plan, at least.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Thanks, that's a reasonable way of handling it.

+ Depending on the dpkg version, bad version may be tolerated or not.
"a bad version" / "bad versions" ?

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'merge_changelog.py'
--- merge_changelog.py 2011-10-25 10:55:57 +0000
+++ merge_changelog.py 2011-12-13 23:30:29 +0000
@@ -26,6 +26,7 @@
2626
27from bzrlib import (27from bzrlib import (
28 merge,28 merge,
29 osutils,
29 )30 )
3031
3132
@@ -77,7 +78,9 @@
77 # don't decorate the messages at all, as dpkg-mergechangelogs78 # don't decorate the messages at all, as dpkg-mergechangelogs
78 # warnings are already prefixed with "dpkg-mergechangelogs:79 # warnings are already prefixed with "dpkg-mergechangelogs:
79 # warning:" which makes the origin of the messages quite clear.80 # warning:" which makes the origin of the messages quite clear.
80 _logger.warning('%s', stderr)81 encoding = osutils.get_user_encoding()
82 # Errors are output using the locale, and log needs unicode.
83 _logger.warning('%s', stderr.decode(encoding, "replace"))
81 if retcode == 1:84 if retcode == 1:
82 # dpkg-mergechangelogs reports a conflict. Unfortunately it uses85 # dpkg-mergechangelogs reports a conflict. Unfortunately it uses
83 # slightly non-standard conflict markers (<http://pad.lv/815700>:86 # slightly non-standard conflict markers (<http://pad.lv/815700>:
@@ -96,6 +99,12 @@
96 return match_text[0] * 799 return match_text[0] * 7
97 stdout = re.sub('(?m)^[<=>]{6}$', replace_func, stdout)100 stdout = re.sub('(?m)^[<=>]{6}$', replace_func, stdout)
98 return 'conflicted', stdout101 return 'conflicted', stdout
102 elif retcode != 0:
103 # dpkg-mergechangelogs exited with an error. There is probably no
104 # output at all, but regardless the merge should fall back to
105 # another method.
106 _logger.warning("dpkg-mergechangelogs failed with status %d", retcode)
107 return 'not_applicable', stdout
99 else:108 else:
100 return 'success', stdout109 return 'success', stdout
101 finally:110 finally:
102111
=== modified file 'tests/test_merge_changelog.py'
--- tests/test_merge_changelog.py 2011-10-14 14:15:43 +0000
+++ tests/test_merge_changelog.py 2011-12-13 23:30:29 +0000
@@ -134,12 +134,6 @@
134# Backports from current testtools so that we remain compatible with testtools134# Backports from current testtools so that we remain compatible with testtools
135# 0.9.2 (the version in lucid).135# 0.9.2 (the version in lucid).
136UTF8_TEXT = ContentType('text', 'plain', {'charset': 'utf8'})136UTF8_TEXT = ContentType('text', 'plain', {'charset': 'utf8'})
137def text_content(text):
138 """Create a `Content` object from some text.
139
140 This is useful for adding details which are short strings.
141 """
142 return Content(UTF8_TEXT, lambda: [text.encode('utf8')])
143137
144138
145class TestMergeChangelog(tests.TestCase):139class TestMergeChangelog(tests.TestCase):
@@ -162,7 +156,8 @@
162 warnings_log = self.logged_warnings.getvalue()156 warnings_log = self.logged_warnings.getvalue()
163 if warnings_log:157 if warnings_log:
164 self.addDetail(158 self.addDetail(
165 'merge_changelog warnings', text_content(warnings_log))159 'merge_changelog warnings',
160 Content(UTF8_TEXT, lambda: [warnings_log]))
166161
167 def assertMergeChangelog(self, expected_lines, this_lines, other_lines,162 def assertMergeChangelog(self, expected_lines, this_lines, other_lines,
168 base_lines=[], conflicted=False):163 base_lines=[], conflicted=False):
@@ -265,6 +260,40 @@
265 conflicted=True260 conflicted=True
266 )261 )
267262
263 def test_invalid_version(self):
264 """An invalid version in the changelog should be handled sanely
265
266 Depending on the dpkg version, bad version may be tolerated or not.
267 If the script aborts the merge should result in a success with zero
268 bytes in the merged file. See lp:893495 for such an issue.
269 """
270 invalid_changelog = """\
271psuedo-prog (\xc2\xa7) unstable; urgency=low
272
273 * New project released!!!!
274
275 -- Barry Foo <barry@example.com> Thu, 28 Jan 2010 10:00:44 +0000
276
277""".splitlines(True)
278 # invalid_changelog has a bad version, with non-ascii characters.
279 status, lines = merge_changelog.merge_changelog(
280 this_lines=v_112_1 + invalid_changelog,
281 other_lines=v_111_2 + invalid_changelog,
282 base_lines=invalid_changelog)
283 log = self.logged_warnings.getvalue()
284 self.assertContainsRe(log, "(?m)\xc2\xa7 is not a valid version$")
285 if "dpkg-mergechangelogs: error:" in log:
286 # Script version aborts on invalid versions so merge must fail
287 self.assertEqual('not_applicable', status)
288 self.assertContainsRe(log,
289 "(?m)dpkg-mergechangelogs failed with status \\d+$")
290 else:
291 # Script version tolerates invalid versions and produces output
292 self.assertEqual('success', status)
293 self.assertEqualDiff(
294 "".join(v_112_1 + v_111_2 + invalid_changelog),
295 "".join(lines))
296
268297
269class TestChangelogHook(tests.TestCaseWithMemoryTransport):298class TestChangelogHook(tests.TestCaseWithMemoryTransport):
270299

Subscribers

People subscribed via source and target branches