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
1=== modified file 'merge_changelog.py'
2--- merge_changelog.py 2011-10-25 10:55:57 +0000
3+++ merge_changelog.py 2011-12-13 23:30:29 +0000
4@@ -26,6 +26,7 @@
5
6 from bzrlib import (
7 merge,
8+ osutils,
9 )
10
11
12@@ -77,7 +78,9 @@
13 # don't decorate the messages at all, as dpkg-mergechangelogs
14 # warnings are already prefixed with "dpkg-mergechangelogs:
15 # warning:" which makes the origin of the messages quite clear.
16- _logger.warning('%s', stderr)
17+ encoding = osutils.get_user_encoding()
18+ # Errors are output using the locale, and log needs unicode.
19+ _logger.warning('%s', stderr.decode(encoding, "replace"))
20 if retcode == 1:
21 # dpkg-mergechangelogs reports a conflict. Unfortunately it uses
22 # slightly non-standard conflict markers (<http://pad.lv/815700>:
23@@ -96,6 +99,12 @@
24 return match_text[0] * 7
25 stdout = re.sub('(?m)^[<=>]{6}$', replace_func, stdout)
26 return 'conflicted', stdout
27+ elif retcode != 0:
28+ # dpkg-mergechangelogs exited with an error. There is probably no
29+ # output at all, but regardless the merge should fall back to
30+ # another method.
31+ _logger.warning("dpkg-mergechangelogs failed with status %d", retcode)
32+ return 'not_applicable', stdout
33 else:
34 return 'success', stdout
35 finally:
36
37=== modified file 'tests/test_merge_changelog.py'
38--- tests/test_merge_changelog.py 2011-10-14 14:15:43 +0000
39+++ tests/test_merge_changelog.py 2011-12-13 23:30:29 +0000
40@@ -134,12 +134,6 @@
41 # Backports from current testtools so that we remain compatible with testtools
42 # 0.9.2 (the version in lucid).
43 UTF8_TEXT = ContentType('text', 'plain', {'charset': 'utf8'})
44-def text_content(text):
45- """Create a `Content` object from some text.
46-
47- This is useful for adding details which are short strings.
48- """
49- return Content(UTF8_TEXT, lambda: [text.encode('utf8')])
50
51
52 class TestMergeChangelog(tests.TestCase):
53@@ -162,7 +156,8 @@
54 warnings_log = self.logged_warnings.getvalue()
55 if warnings_log:
56 self.addDetail(
57- 'merge_changelog warnings', text_content(warnings_log))
58+ 'merge_changelog warnings',
59+ Content(UTF8_TEXT, lambda: [warnings_log]))
60
61 def assertMergeChangelog(self, expected_lines, this_lines, other_lines,
62 base_lines=[], conflicted=False):
63@@ -265,6 +260,40 @@
64 conflicted=True
65 )
66
67+ def test_invalid_version(self):
68+ """An invalid version in the changelog should be handled sanely
69+
70+ Depending on the dpkg version, bad version may be tolerated or not.
71+ If the script aborts the merge should result in a success with zero
72+ bytes in the merged file. See lp:893495 for such an issue.
73+ """
74+ invalid_changelog = """\
75+psuedo-prog (\xc2\xa7) unstable; urgency=low
76+
77+ * New project released!!!!
78+
79+ -- Barry Foo <barry@example.com> Thu, 28 Jan 2010 10:00:44 +0000
80+
81+""".splitlines(True)
82+ # invalid_changelog has a bad version, with non-ascii characters.
83+ status, lines = merge_changelog.merge_changelog(
84+ this_lines=v_112_1 + invalid_changelog,
85+ other_lines=v_111_2 + invalid_changelog,
86+ base_lines=invalid_changelog)
87+ log = self.logged_warnings.getvalue()
88+ self.assertContainsRe(log, "(?m)\xc2\xa7 is not a valid version$")
89+ if "dpkg-mergechangelogs: error:" in log:
90+ # Script version aborts on invalid versions so merge must fail
91+ self.assertEqual('not_applicable', status)
92+ self.assertContainsRe(log,
93+ "(?m)dpkg-mergechangelogs failed with status \\d+$")
94+ else:
95+ # Script version tolerates invalid versions and produces output
96+ self.assertEqual('success', status)
97+ self.assertEqualDiff(
98+ "".join(v_112_1 + v_111_2 + invalid_changelog),
99+ "".join(lines))
100+
101
102 class TestChangelogHook(tests.TestCaseWithMemoryTransport):
103

Subscribers

People subscribed via source and target branches