[Pkg-bazaar-commits] ./bzr-builddeb/trunk r363: Merge merge-package command from Muharem.
James Westby
james.westby at canonical.com
Mon Aug 24 17:33:44 UTC 2009
------------------------------------------------------------
revno: 363 [merge]
committer: James Westby <james.westby at canonical.com>
branch nick: trunk
timestamp: Mon 2009-08-24 18:33:44 +0100
message:
Merge merge-package command from Muharem.
merge-package allows you to merge another package branch, ensuring that
there aren't spurious conflicts due to divergence in the upstream ancestry.
added:
merge_package.py
tests/test_merge_package.py
modified:
__init__.py
cmds.py
errors.py
import_dsc.py
tests/__init__.py
upstream.py
-------------- next part --------------
=== modified file '__init__.py'
--- a/__init__.py 2009-07-26 15:51:02 +0000
+++ b/__init__.py 2009-08-24 17:33:44 +0000
@@ -39,7 +39,8 @@
"merge_upstream": ["mu"],
"import_dsc": [],
"bd_do": [],
- "mark_uploaded": []
+ "mark_uploaded": [],
+ "merge_package": [],
}
for command, aliases in commands.iteritems():
=== modified file 'cmds.py'
--- a/cmds.py 2009-08-18 20:11:05 +0000
+++ b/cmds.py 2009-08-24 17:33:44 +0000
@@ -69,6 +69,7 @@
DscCache,
DscComp,
)
+from bzrlib.plugins.builddeb.merge_package import fix_ancestry_as_needed
from bzrlib.plugins.builddeb.source_distiller import (
FullSourceDistiller,
MergeModeDistiller,
@@ -722,9 +723,9 @@
"the previous upstream version, %s, in the "
"branch: %s" % (last_version,
db.upstream_tag_name(last_version)))
- upstream_tip = db._revid_of_upstream_version_from_branch(
+ upstream_tip = db.revid_of_upstream_version_from_branch(
last_version)
- db._extract_upstream_tree(upstream_tip, tempdir)
+ db.extract_upstream_tree(upstream_tip, tempdir)
else:
db._create_empty_upstream_tree(tempdir)
self.import_many(db, files_list, orig_target)
@@ -873,6 +874,45 @@
t.unlock()
+class cmd_merge_package(Command):
+ """Merges source packaging branch into target packaging branch.
+
+ This will first check whether the upstream branches have diverged.
+
+ If that's the case an attempt will be made to fix the upstream ancestry
+ so that the user only needs to deal wth packaging branch merge issues.
+
+ In the opposite case a normal merge will be performed.
+ """
+ takes_args = ['source']
+
+ def run(self, source):
+ source_branch = target_branch = None
+ # Get the target branch.
+ try:
+ tree = WorkingTree.open_containing('.')[0]
+ target_branch = tree.branch
+ except NotBranchError:
+ raise BzrCommandError(
+ "There is no tree to merge the source branch in to")
+ # Get the source branch.
+ try:
+ source_branch = Branch.open(source)
+ except NotBranchError:
+ raise BzrCommandError("Invalid source branch URL?")
+
+ fix_ancestry_as_needed(tree, source_branch)
+
+ # Merge source packaging branch in to the target packaging branch.
+ conflicts = tree.merge_from_branch(source_branch)
+ if conflicts > 0:
+ info('The merge resulted in %s conflicts. Please resolve these '
+ 'and commit the changes with "bzr commit".' % conflicts)
+ else:
+ info('The merge resulted in no conflicts. You may commit the '
+ 'changes by running "bzr commit".')
+
+
class cmd_test_builddeb(Command):
"""Run the builddeb test suite"""
@@ -883,4 +923,3 @@
passed = selftest(test_suite_factory=test_suite)
# invert for shell exit code rules
return not passed
-
=== modified file 'errors.py'
--- a/errors.py 2009-04-16 09:30:49 +0000
+++ b/errors.py 2009-08-24 16:27:40 +0000
@@ -175,3 +175,12 @@
def __init__(self, error):
BzrError.__init__(self, error=error)
+
+
+class SharedUpstreamConflictsWithTargetPackaging(BzrError):
+ _fmt = ('The upstream branches for the merge source and target have '
+ 'diverged. Unfortunately, the attempt to fix this problem '
+ 'resulted in conflicts. Please resolve these, commit and '
+ 're-run the "merge-package" command to finish. '
+ 'Alternatively, until you commit you can use "bzr revert" to '
+ 'restore the state of the unmerged branch.')
=== modified file 'import_dsc.py'
--- a/import_dsc.py 2009-07-26 16:44:17 +0000
+++ b/import_dsc.py 2009-08-19 12:22:29 +0000
@@ -1570,11 +1570,12 @@
finally:
shutil.rmtree(tempdir)
- def _extract_upstream_tree(self, upstream_tip, basedir):
+ def extract_upstream_tree(self, upstream_tip, basedir):
# Extract that to a tempdir so we can get a working
# tree for it.
# TODO: should stack rather than trying to use the repository,
# as that will be more efficient.
+ # TODO: remove the _extract_upstream_tree alias below.
to_location = os.path.join(basedir, "upstream")
dir_to = self.branch.bzrdir.sprout(to_location,
revision_id=upstream_tip,
@@ -1582,6 +1583,8 @@
self.upstream_tree = dir_to.open_workingtree()
self.upstream_branch = self.upstream_tree.branch
+ _extract_upstream_tree = extract_upstream_tree
+
def _create_empty_upstream_tree(self, basedir):
to_location = os.path.join(basedir, "upstream")
to_transport = get_transport(to_location)
@@ -1615,7 +1618,11 @@
shutil.rmtree(tempdir)
raise
- def _revid_of_upstream_version_from_branch(self, version):
+ """The private method below will go away eventually."""
+ return self.revid_of_upstream_version_from_branch(version)
+
+ def revid_of_upstream_version_from_branch(self, version):
+ # TODO: remove the _revid_of_upstream_version_from_branch alias below.
assert isinstance(version, str)
tag_name = self.upstream_tag_name(version)
if self._has_version(self.branch, tag_name):
@@ -1629,6 +1636,8 @@
tag_name = self.upstream_tag_name(version)
return self.branch.tags.lookup_tag(tag_name)
+ _revid_of_upstream_version_from_branch = revid_of_upstream_version_from_branch
+
def merge_upstream(self, tarball_filename, version, previous_version,
upstream_branch=None, upstream_revision=None, merge_type=None):
assert self.upstream_branch is None, \
@@ -1639,14 +1648,14 @@
if previous_version is not None:
if self.has_upstream_version_in_packaging_branch(
previous_version.upstream_version):
- upstream_tip = self._revid_of_upstream_version_from_branch(
+ upstream_tip = self.revid_of_upstream_version_from_branch(
previous_version.upstream_version)
- self._extract_upstream_tree(upstream_tip, tempdir)
+ self.extract_upstream_tree(upstream_tip, tempdir)
elif (upstream_branch is not None and
previous_upstream_revision is not None):
upstream_tip = RevisionSpec.from_string(previous_upstream_revision).as_revision_id(upstream_branch)
assert isinstance(upstream_tip, str)
- self._extract_upstream_tree(upstream_tip, tempdir)
+ self.extract_upstream_tree(upstream_tip, tempdir)
else:
raise BzrCommandError("Unable to find the tag for the "
"previous upstream version, %s, in the branch: "
=== added file 'merge_package.py'
--- a/merge_package.py 1970-01-01 00:00:00 +0000
+++ b/merge_package.py 2009-08-24 10:08:59 +0000
@@ -0,0 +1,168 @@
+# merge_package.py -- The plugin for bzr
+# Copyright (C) 2009 Canonical Ltd.
+#
+# :Author: Muharem Hrnjadovic <muharem at ubuntu.com>
+#
+# This file is part of bzr-builddeb.
+#
+# bzr-builddeb is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# bzr-builddeb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with bzr-builddeb; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+import os
+import re
+import sys
+import tempfile
+
+from debian_bundle.changelog import Version
+
+from bzrlib import errors
+
+from bzrlib.plugins.builddeb.import_dsc import DistributionBranch
+from bzrlib.plugins.builddeb.util import find_changelog
+
+
+def _latest_version(branch):
+ """Version of the most recent source package upload in the given `branch`.
+
+ :param branch: A Branch object containing the source upload of interest.
+ """
+ changelog, _ignore = find_changelog(branch.basis_tree(), False)
+
+ return changelog.version
+
+
+def _upstream_version_data(source, target):
+ """Most recent upstream versions/revision IDs of the merge source/target.
+
+ Please note: both packaging branches must have been read-locked
+ beforehand.
+
+ :param source: The merge source branch.
+ :param target: The merge target branch.
+ """
+ results = list()
+ for branch in (source, target):
+ db = DistributionBranch(branch, branch)
+ uver = _latest_version(branch).upstream_version
+ results.append((uver, db.revid_of_upstream_version_from_branch(uver)))
+
+ return results
+
+
+def fix_ancestry_as_needed(tree, source):
+ """Manipulate the merge target's ancestry to avoid upstream conflicts.
+
+ Merging J->I given the following ancestry tree is likely to result in
+ upstream merge conflicts:
+
+ debian-upstream ,------------------H
+ A-----------B \
+ ubuntu-upstream \ \`-------G \
+ \ \ \ \
+ debian-packaging \ ,---------D--------\-----------J
+ C \ \
+ ubuntu-packaging `----E------F--------I
+
+ Here there was a new upstream release (G) that Ubuntu packaged (I), and
+ then another one that Debian packaged, skipping G, at H and J.
+
+ Now, the way to solve this is to introduce the missing link.
+
+ debian-upstream ,------------------H------.
+ A-----------B \ \
+ ubuntu-upstream \ \`-------G-----------\------K
+ \ \ \ \
+ debian-packaging \ ,---------D--------\-----------J
+ C \ \
+ ubuntu-packaging `----E------F--------I
+
+ at K, which isn't a real merge, as we just use the tree from H, but add
+ G as a parent and then we merge that in to Ubuntu.
+
+ debian-upstream ,------------------H------.
+ A-----------B \ \
+ ubuntu-upstream \ \`-------G-----------\------K
+ \ \ \ \ \
+ debian-packaging \ ,---------D--------\-----------J \
+ C \ \ \
+ ubuntu-packaging `----E------F--------I------------------L
+
+ At this point we can merge J->L to merge the Debian and Ubuntu changes.
+
+ :param tree: The `WorkingTree` of the merge target branch.
+ :param source: The merge source (packaging) branch.
+ """
+ upstreams_diverged = False
+ t_upstream_reverted = False
+ target = tree.branch
+
+ source.lock_read()
+ try:
+ tree.lock_write()
+ try:
+ # "Unpack" the upstream versions and revision ids for the merge
+ # source and target branch respectively.
+ [(us_ver, us_revid), (ut_ver, ut_revid)] = _upstream_version_data(source, target)
+
+ # Did the upstream branches of the merge source/target diverge?
+ graph = source.repository.get_graph(target.repository)
+ upstreams_diverged = (len(graph.heads([us_revid, ut_revid])) > 1)
+
+ # No, we're done!
+ if not upstreams_diverged:
+ return (upstreams_diverged, t_upstream_reverted)
+
+ # Instantiate a `DistributionBranch` object for the merge target
+ # (packaging) branch.
+ db = DistributionBranch(tree.branch, tree.branch)
+ tempdir = tempfile.mkdtemp(dir=os.path.join(tree.basedir, '..'))
+
+ # Extract the merge target's upstream tree into a temporary
+ # directory.
+ db.extract_upstream_tree(ut_revid, tempdir)
+ tmp_target_utree = db.upstream_tree
+
+ # Merge upstream branch tips to obtain a shared upstream parent.
+ # This will add revision K (see graph above) to a temporary merge
+ # target upstream tree.
+ tmp_target_utree.lock_write()
+ try:
+ if us_ver > ut_ver:
+ # The source upstream tree is more recent and the
+ # temporary target tree needs to be reshaped to match it.
+ tmp_target_utree.revert(
+ None, source.repository.revision_tree(us_revid))
+ t_upstream_reverted = True
+
+ tmp_target_utree.set_parent_ids((ut_revid, us_revid))
+ tmp_target_utree.commit(
+ 'Prepared upstream tree for merging into target branch.')
+ finally:
+ tmp_target_utree.unlock()
+
+ # Merge shared upstream parent into the target merge branch. This
+ # creates revison L in the digram above.
+ conflicts = tree.merge_from_branch(tmp_target_utree.branch)
+ if conflicts > 0:
+ raise errors.SharedUpstreamConflictsWithTargetPackaging()
+ else:
+ tree.commit('Merging shared upstream rev into target branch.')
+
+ finally:
+ tree.unlock()
+ finally:
+ source.unlock()
+
+ return (upstreams_diverged, t_upstream_reverted)
=== modified file 'tests/__init__.py'
--- a/tests/__init__.py 2009-07-04 20:45:01 +0000
+++ b/tests/__init__.py 2009-08-19 09:56:50 +0000
@@ -118,6 +118,7 @@
'test_config',
'test_hooks',
'test_import_dsc',
+ 'test_merge_package',
'test_merge_upstream',
'test_repack_tarball_extra',
'test_revspec',
=== added file 'tests/test_merge_package.py'
--- a/tests/test_merge_package.py 1970-01-01 00:00:00 +0000
+++ b/tests/test_merge_package.py 2009-08-24 10:47:13 +0000
@@ -0,0 +1,537 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-15 -*-
+# test_merge_package.py -- Merge packaging branches, fix ancestry as needed.
+# Copyright (C) 2008 Canonical Ltd.
+#
+# This file is part of bzr-builddeb.
+#
+# bzr-builddeb is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# bzr-builddeb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with bzr-builddeb; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import string
+import unittest
+
+from debian_bundle.changelog import Version
+
+from bzrlib.errors import ConflictsInTree
+from bzrlib.tests import TestCaseWithTransport
+
+from bzrlib.plugins.builddeb import merge_package as MP
+from bzrlib.plugins.builddeb.import_dsc import DistributionBranch
+
+_Debian_changelog = '''\
+ipsec-tools (%s) unstable; urgency=high
+
+ * debian packaging -- %s
+
+ -- Nico Golde <nion at debian.org> Tue, %02d May 2009 13:26:14 +0200
+
+'''
+
+_Ubuntu_changelog = '''\
+ipsec-tools (%s) karmic; urgency=low
+
+ * ubuntu packaging -- %s
+
+ -- Jamie Strandboge <jamie at ubuntu.com> Fri, %02d Jul 2009 13:24:17 -0500
+
+'''
+
+
+def _prepend_log(text, path):
+ content = open(path).read()
+ fh = open(path, 'wb')
+ try:
+ fh.write(text+content)
+ finally:
+ fh.close()
+
+
+class MergePackageTests(TestCaseWithTransport):
+
+ def test_latest_upstream_versions(self):
+ """Check correctness of upstream version computation."""
+ ubup_o, debp_n, _ubuu, _debu = self._setup_debian_upstream_newer()
+ # Ubuntu upstream.
+ self.assertEquals(
+ MP._latest_version(ubup_o).upstream_version, '1.1.2')
+ # Debian upstream.
+ self.assertEquals(
+ MP._latest_version(debp_n).upstream_version, '2.0')
+
+ ubuntup, debianp = self._setup_upstreams_not_diverged()
+ # Ubuntu upstream.
+ self.assertEquals(
+ MP._latest_version(ubuntup).upstream_version, '1.4')
+ # Debian upstream.
+ self.assertEquals(
+ MP._latest_version(debianp).upstream_version, '2.2')
+
+ def test_debian_upstream_newer(self):
+ """Diverging upstreams (debian newer) don't cause merge conflicts.
+
+ The debian and ubuntu upstream branches will differ with regard to
+ the content of the file 'c'.
+
+ Furthermore the respective packaging branches will have a text
+ conflict in 'debian/changelog'.
+
+ The upstream conflict will be resolved by fix_ancestry_as_needed().
+ Please note that the debian ancestry is more recent.
+ """
+ ubup, debp, ubuu, debu = self._setup_debian_upstream_newer()
+
+ # Attempt a plain merge first.
+ conflicts = ubup.merge_from_branch(
+ debp.branch, to_revision=self.revid_debp_n_C)
+
+ # There are two conflicts in the 'c' and the 'debian/changelog' files
+ # respectively.
+ self.assertEquals(conflicts, 2)
+ conflict_paths = sorted([c.path for c in ubup.conflicts()])
+ self.assertEquals(conflict_paths, [u'c.moved', u'debian/changelog'])
+
+ # Undo the failed merge.
+ ubup.revert()
+
+ # Check the versions present in the tree with the fixed ancestry.
+ v3 = "1.1.2"
+ v4 = "2.0"
+ db1 = DistributionBranch(ubup.branch, ubup.branch)
+ self.assertEqual(db1.has_upstream_version(v3), True)
+ # This version is in the diverged debian upstream tree and will
+ # hence not be present in the target ubuntu packaging branch.
+ self.assertEqual(db1.has_upstream_version(v4), False)
+
+ # The ubuntu upstream branch tip.
+ ubuu_tip = ubuu.branch.revision_history()[-1]
+ # The debian upstream branch tip.
+ debu_tip = debu.branch.revision_history()[-1]
+ # The ubuntu packaging branch tip.
+ ubup_tip_pre_fix = ubup.branch.revision_history()[-1]
+
+ # The first conflict is resolved by calling fix_ancestry_as_needed().
+ upstreams_diverged, t_upstream_reverted = MP.fix_ancestry_as_needed(ubup, debp.branch)
+
+ # The ancestry did diverge and needed to be fixed.
+ self.assertEquals(upstreams_diverged, True)
+ # The (temporary) target upstream branch had to be reverted to the
+ # source upstream branch since the latter was more recent.
+ self.assertEquals(t_upstream_reverted, True)
+
+ # Check the versions present in the tree with the fixed ancestry.
+ db2 = DistributionBranch(ubup.branch, ubup.branch)
+ self.assertEqual(db2.has_upstream_version(v3), True)
+ # The ancestry has been fixed and the missing debian upstream
+ # version should now be present in the target ubuntu packaging
+ # branch.
+ self.assertEqual(db2.has_upstream_version(v4), True)
+
+ # Now let's take a look at the fixed ubuntu packaging branch.
+ ubup_tip_post_fix = ubup.branch.revision_history()[-1]
+ ubup_parents_post_fix = ubup.branch.repository.revision_tree(ubup_tip_post_fix).get_parent_ids()
+
+ # The tip of the fixed ubuntu packaging branch has 2 parents.
+ self.assertEquals(len(ubup_parents_post_fix), 2)
+
+ # The left parent is the packaging branch tip before fixing.
+ self.assertEquals(ubup_parents_post_fix[0], ubup_tip_pre_fix)
+
+ # The right parent is derived from a merge
+ ubup_parents_sharedupstream = ubup.branch.repository.revision_tree(ubup_parents_post_fix[1]).get_parent_ids()
+ self.assertEquals(ubup_parents_sharedupstream, [ubuu_tip, debu_tip])
+
+ # Try merging again.
+ conflicts = ubup.merge_from_branch(
+ debp.branch, to_revision=self.revid_debp_n_C)
+
+ # And, voila, only the packaging branch conflict remains.
+ self.assertEquals(conflicts, 1)
+ conflict_paths = sorted([c.path for c in ubup.conflicts()])
+ self.assertEquals(conflict_paths, [u'debian/changelog'])
+
+ def test_debian_upstream_older(self):
+ """Diverging upstreams (debian older) don't cause merge conflicts.
+
+ The debian and ubuntu upstream branches will differ with regard to
+ the content of the file 'c'.
+
+ Furthermore the respective packaging branches will have a text
+ conflict in 'debian/changelog'.
+
+ The upstream conflict will be resolved by fix_ancestry_as_needed().
+ Please note that the debian ancestry is older in this case.
+ """
+ ubup, debp, _ubuu, _debu = self._setup_debian_upstream_older()
+
+ # Attempt a plain merge first.
+ conflicts = ubup.merge_from_branch(
+ debp.branch, to_revision=self.revid_debp_o_C)
+
+ # There are two conflicts in the 'c' and the 'debian/changelog' files
+ # respectively.
+ self.assertEquals(conflicts, 2)
+ conflict_paths = sorted([c.path for c in ubup.conflicts()])
+ self.assertEquals(conflict_paths, [u'c.moved', u'debian/changelog'])
+
+ # Undo the failed merge.
+ ubup.revert()
+
+ # The first conflict is resolved by calling fix_ancestry_as_needed().
+ upstreams_diverged, t_upstream_reverted = MP.fix_ancestry_as_needed(ubup, debp.branch)
+
+ # The ancestry did diverge and needed to be fixed.
+ self.assertEquals(upstreams_diverged, True)
+ # The target upstream branch was more recent in this case and hence
+ # was not reverted to the source upstream branch.
+ self.assertEquals(t_upstream_reverted, False)
+
+ # Try merging again.
+ conflicts = ubup.merge_from_branch(
+ debp.branch, to_revision=self.revid_debp_o_C)
+
+ # And, voila, only the packaging branch conflict remains.
+ self.assertEquals(conflicts, 1)
+ conflict_paths = sorted([c.path for c in ubup.conflicts()])
+ self.assertEquals(conflict_paths, [u'debian/changelog'])
+
+ def test_upstreams_not_diverged(self):
+ """Non-diverging upstreams result in a normal merge.
+
+ The debian and ubuntu upstream branches will not have diverged
+ this time.
+
+ The packaging branches will have a conflict in 'debian/changelog'.
+ fix_ancestry_as_needed() will return as soon as establishing that
+ the upstreams have not diverged.
+ """
+ ubuntup, debianp = self._setup_upstreams_not_diverged()
+
+ # Attempt a plain merge first.
+ conflicts = ubuntup.merge_from_branch(
+ debianp.branch, to_revision=self.revid_debianp_C)
+
+ # There is only a conflict in the 'debian/changelog' file.
+ self.assertEquals(conflicts, 1)
+ conflict_paths = sorted([c.path for c in ubuntup.conflicts()])
+ self.assertEquals(conflict_paths, [u'debian/changelog'])
+
+ # Undo the failed merge.
+ ubuntup.revert()
+
+ # The conflict is *not* resolved by calling fix_ancestry_as_needed().
+ upstreams_diverged, t_upstream_reverted = MP.fix_ancestry_as_needed(ubuntup, debianp.branch)
+
+ # The ancestry did *not* diverge.
+ self.assertEquals(upstreams_diverged, False)
+ # The upstreams have not diverged, hence no need to fix/revert
+ # either of them.
+ self.assertEquals(t_upstream_reverted, False)
+
+ # Try merging again.
+ conflicts = ubuntup.merge_from_branch(
+ debianp.branch, to_revision=self.revid_debianp_C)
+
+ # The packaging branch conflict we saw above is still there.
+ self.assertEquals(conflicts, 1)
+ conflict_paths = sorted([c.path for c in ubuntup.conflicts()])
+ self.assertEquals(conflict_paths, [u'debian/changelog'])
+
+ def _setup_debian_upstream_newer(self):
+ """
+ Set up the following test configuration (debian upstream newer).
+
+ debian-upstream ,------------------H
+ A-----------B \
+ ubuntu-upstream \ \`-------G \
+ \ \ \ \
+ debian-packaging \ ,---------D--------\-----------J
+ C \
+ ubuntu-packaging `----E---------------I
+
+ where:
+ - A = 1.0
+ - B = 1.1
+ - H = 2.0
+
+ - G = 1.1.2
+
+ - C = 1.0-1
+ - D = 1.1-1
+ - J = 2.0-1
+
+ - E = 1.0-1ubuntu1
+ - I = 1.1.2-0ubuntu1
+
+ Please note that the debian and ubuntu branches will have a conflict
+ with respect to the file 'c'.
+ """
+ # Set up the debian upstream branch.
+ name = 'debu-n'
+ vdata = [
+ ('upstream-1.0', ('a',), None, None),
+ ('upstream-1.1', ('b',), None, None),
+ ('upstream-2.0', ('c',), None, None),
+ ]
+ debu_n = self._setup_branch(name, vdata)
+
+ # Set up the debian packaging branch.
+ name = 'debp-n'
+ debp_n = self.make_branch_and_tree(name)
+ debp_n.pull(debu_n.branch, stop_revision=self.revid_debu_n_A)
+
+ vdata = [
+ ('1.0-1', ('debian/', 'debian/changelog'), None, None),
+ ('1.1-1', ('o',), debu_n, self.revid_debu_n_B),
+ ('2.0-1', ('p',), debu_n, self.revid_debu_n_C),
+ ]
+ self._setup_branch(name, vdata, debp_n, 'd')
+
+ # Set up the ubuntu upstream branch.
+ name = 'ubuu-o'
+ ubuu_o = debu_n.bzrdir.sprout(
+ name, revision_id=self.revid_debu_n_B).open_workingtree()
+
+ vdata = [
+ ('upstream-1.1.2', ('c',), None, None),
+ ]
+ self._setup_branch(name, vdata, ubuu_o)
+
+ # Set up the ubuntu packaging branch.
+ name = 'ubup-o'
+ ubup_o = debu_n.bzrdir.sprout(
+ name, revision_id=self.revid_debu_n_A).open_workingtree()
+
+ vdata = [
+ ('1.0-1ubuntu1', (), debp_n, self.revid_debp_n_A),
+ ('1.1.2-0ubuntu1', (), ubuu_o, self.revid_ubuu_o_A),
+ ]
+ self._setup_branch(name, vdata, ubup_o, 'u')
+
+ # Return the ubuntu and the debian packaging branches.
+ return (ubup_o, debp_n, ubuu_o, debu_n)
+
+ def _setup_debian_upstream_older(self):
+ """
+ Set up the following test configuration (debian upstream older).
+
+ debian-upstream ,----H-------------.
+ A-----------B \
+ ubuntu-upstream \ \`-----------G \
+ \ \ \ \
+ debian-packaging \ ,---------D------------\-------J
+ C \
+ ubuntu-packaging `----E-------------------I
+
+ where:
+ - A = 1.0
+ - B = 1.1
+ - H = 1.1.3
+
+ - G = 2.1
+
+ - C = 1.0-1
+ - D = 1.1-1
+ - J = 1.1.3-1
+
+ - E = 1.0-1ubuntu1
+ - I = 2.1-0ubuntu1
+
+ Please note that the debian and ubuntu branches will have a conflict
+ with respect to the file 'c'.
+ """
+ # Set up the debian upstream branch.
+ name = 'debu-o'
+ vdata = [
+ ('upstream-1.0', ('a',), None, None),
+ ('upstream-1.1', ('b',), None, None),
+ ('upstream-1.1.3', ('c',), None, None),
+ ]
+ debu_o = self._setup_branch(name, vdata)
+
+ # Set up the debian packaging branch.
+ name = 'debp-o'
+ debp_o = self.make_branch_and_tree(name)
+ debp_o.pull(debu_o.branch, stop_revision=self.revid_debu_o_A)
+
+ vdata = [
+ ('1.0-1', ('debian/', 'debian/changelog'), None, None),
+ ('1.1-1', ('o',), debu_o, self.revid_debu_o_B),
+ ('1.1.3-1', ('p',), debu_o, self.revid_debu_o_C),
+ ]
+ self._setup_branch(name, vdata, debp_o, 'd')
+
+ # Set up the ubuntu upstream branch.
+ name = 'ubuu-n'
+ ubuu_n = debu_o.bzrdir.sprout(
+ name, revision_id=self.revid_debu_o_B).open_workingtree()
+
+ vdata = [
+ ('upstream-2.1', ('c',), None, None),
+ ]
+ self._setup_branch(name, vdata, ubuu_n)
+
+ # Set up the ubuntu packaging branch.
+ name = 'ubup-n'
+ ubup_n = debu_o.bzrdir.sprout(
+ name, revision_id=self.revid_debu_o_A).open_workingtree()
+
+ vdata = [
+ ('1.0-1ubuntu1', (), debp_o, self.revid_debp_o_A),
+ ('2.1-0ubuntu1', (), ubuu_n, self.revid_ubuu_n_A),
+ ]
+ self._setup_branch(name, vdata, ubup_n, 'u')
+
+ # Return the ubuntu and the debian packaging branches.
+ return (ubup_n, debp_o, ubuu_n, debu_o)
+
+ def _setup_upstreams_not_diverged(self):
+ """
+ Set up a test configuration where the usptreams have not diverged.
+
+ debian-upstream .-----G
+ A-----------B-----H \
+ ubuntu-upstream \ \ \ \
+ \ \ \ \
+ debian-packaging \ ,---------D-----\-------J
+ C \
+ ubuntu-packaging `----E------------I
+
+ where:
+ - A = 1.0
+ - B = 1.1
+ - H = 1.4
+
+ - G = 2.2
+
+ - C = 1.0-1
+ - D = 1.1-1
+ - J = 2.2-1
+
+ - E = 1.0-1ubuntu1
+ - I = 1.4-0ubuntu1
+
+ Please note that there's only one shared upstream branch in this case.
+ """
+ # Set up the upstream branch.
+ name = 'upstream'
+ vdata = [
+ ('upstream-1.0', ('a',), None, None),
+ ('upstream-1.1', ('b',), None, None),
+ ('upstream-1.4', ('c',), None, None),
+ ]
+ upstream = self._setup_branch(name, vdata)
+
+ # Set up the debian upstream branch.
+ name = 'dupstream'
+ dupstream = upstream.bzrdir.sprout(name).open_workingtree()
+ vdata = [
+ ('upstream-2.2', (), None, None),
+ ]
+ dupstream = self._setup_branch(name, vdata, dupstream)
+
+ # Set up the debian packaging branch.
+ name = 'debianp'
+ debianp = self.make_branch_and_tree(name)
+ debianp.pull(dupstream.branch, stop_revision=self.revid_upstream_A)
+
+ vdata = [
+ ('1.0-1', ('debian/', 'debian/changelog'), None, None),
+ ('1.1-1', ('o',), dupstream, self.revid_upstream_B),
+ ('2.2-1', ('p',), dupstream, self.revid_dupstream_A),
+ ]
+ self._setup_branch(name, vdata, debianp, 'd')
+
+ # Set up the ubuntu packaging branch.
+ name = 'ubuntup'
+ ubuntup = upstream.bzrdir.sprout(
+ name, revision_id=self.revid_upstream_A).open_workingtree()
+
+ vdata = [
+ ('1.0-1ubuntu1', (), debianp, self.revid_debianp_A),
+ ('1.4-0ubuntu1', (), upstream, self.revid_upstream_C),
+ ]
+ self._setup_branch(name, vdata, ubuntup, 'u')
+
+ # Return the ubuntu and the debian packaging branches.
+ return (ubuntup, debianp)
+
+ def _setup_branch(self, name, vdata, tree=None, log_format=None):
+ vids = list(string.ascii_uppercase)
+ days = range(len(string.ascii_uppercase))
+
+ if tree is None:
+ tree = self.make_branch_and_tree(name)
+
+ tree.lock_write()
+ self.addCleanup(tree.unlock)
+
+ def revid_name(vid):
+ return 'revid_%s_%s' % (name.replace('-', '_'), vid)
+
+ def add_paths(paths):
+ qpaths = ['%s/%s' % (name, path) for path in paths]
+ self.build_tree(qpaths)
+ tree.add(paths)
+
+ def changelog(vdata, vid):
+ result = ''
+ day = days.pop(0)
+ if isinstance(vdata, tuple):
+ uver, dver = vdata[:2]
+ ucle = _Ubuntu_changelog % (uver, vid, day)
+ dcle = _Debian_changelog % (dver, vid, day)
+ result = ucle + dcle
+ else:
+ if log_format == 'u':
+ result = _Ubuntu_changelog % (vdata, vid, day)
+ elif log_format == 'd':
+ result = _Debian_changelog % (vdata, vid, day)
+
+ return result
+
+ def commit(msg, version):
+ vid = vids.pop(0)
+ if log_format is not None:
+ cle = changelog(version, vid)
+ p = '%s/work/%s/debian/changelog' % (self.test_base_dir, name)
+ _prepend_log(cle, p)
+ revid = tree.commit('%s: %s' % (vid, msg))
+ setattr(self, revid_name(vid), revid)
+ tree.branch.tags.set_tag(version, revid)
+
+ def tree_nick(tree):
+ return str(tree)[1:-1].split('/')[-1]
+
+ for version, paths, utree, urevid in vdata:
+ msg = ''
+ if utree is not None:
+ tree.merge_from_branch(utree.branch, to_revision=urevid)
+ utree.branch.tags.merge_to(tree.branch.tags)
+ if urevid is not None:
+ msg += 'Merged tree %s|%s. ' % (tree_nick(utree), urevid)
+ else:
+ msg += 'Merged tree %s. ' % utree
+ if paths is not None:
+ add_paths(paths)
+ msg += 'Added paths: %s. ' % str(paths)
+
+ commit(msg, version)
+
+ return tree
+
+
+if __name__ == '__main__':
+ suite = unittest.TestLoader().loadTestsFromTestCase(MergePackageTests)
+ unittest.TextTestRunner(verbosity=2).run(suite)
=== modified file 'upstream.py'
--- a/upstream.py 2009-08-14 10:52:10 +0000
+++ b/upstream.py 2009-08-24 17:33:44 +0000
@@ -79,7 +79,7 @@
db = DistributionBranch(self.branch, None, tree=self.tree)
if not db.has_upstream_version_in_packaging_branch(version):
raise PackageVersionNotPresent(package, version, self)
- revid = db._revid_of_upstream_version_from_branch(version)
+ revid = db.revid_of_upstream_version_from_branch(version)
if not db.has_pristine_tar_delta(revid):
raise PackageVersionNotPresent(package, version, self)
info("Using pristine-tar to reconstruct the needed tarball.")
More information about the Pkg-bazaar-commits
mailing list