[Pkg-bazaar-commits] ./bzr-builddeb/trunk.old r229: Use file ids from other trees.

James Westby jw+debian at jameswestby.net
Wed Dec 10 08:32:46 UTC 2008


------------------------------------------------------------
revno: 229
committer: James Westby <jw+debian at jameswestby.net>
branch nick: import
timestamp: Tue 2008-06-10 14:13:04 +0100
message:
  Use file ids from other trees.
  
  When there are parallel imports of files the file ids should be shared.
  
  This change picks up the file ids from the other trees of the same type
  (upstream or debian), and uses them if the file can't be found in any
  parent.
  
  It should perhaps be extended to just use a file id from any branch,
  including one of a different type.
modified:
  import_dsc.py
  tests/test_import_dsc.py
  tree_patcher.py
-------------- next part --------------
=== modified file 'import_dsc.py'
--- a/import_dsc.py	2008-06-04 10:08:21 +0000
+++ b/import_dsc.py	2008-06-10 13:13:04 +0000
@@ -122,6 +122,9 @@
     prefix = common_directory(names_of_files(archive_file))
     tt = TreeTransform(tree)
 
+    if file_ids_from is None:
+        file_ids_from = []
+
     removed = set()
     for path, entry in tree.inventory.iter_entries():
         if entry.parent_id is None:
@@ -167,12 +170,15 @@
         else:
             raise UnknownType(relative_path)
         if tt.tree_file_id(trans_id) is None:
-            if (file_ids_from is not None and
-                file_ids_from.has_filename(relative_path)):
-                file_id = file_ids_from.path2id(relative_path)
-                assert file_id is not None
-                tt.version_file(file_id, trans_id)
-            else:
+            found = False
+            for other_tree in file_ids_from:
+                if other_tree.has_filename(relative_path):
+                    file_id = other_tree.path2id(relative_path)
+                    assert file_id is not None
+                    tt.version_file(file_id, trans_id)
+                    found = True
+                    break
+            if not found:
                 name = basename(member.name.rstrip('/'))
                 file_id = generate_ids.gen_file_id(name)
                 tt.version_file(file_id, trans_id)
@@ -184,12 +190,15 @@
         path = tree.abspath(relative_path)
         do_directory(tt, trans_id, tree, relative_path, path)
         if tt.tree_file_id(trans_id) is None:
-            if (file_ids_from is not None and
-                file_ids_from.has_filename(relative_path)):
-                file_id = file_ids_from.path2id(relative_path)
-                assert file_id is not None
-                tt.version_file(file_id, trans_id)
-            else:
+            found = False
+            for other_tree in file_ids_from:
+                if other_tree.has_filename(relative_path):
+                    file_id = other_tree.path2id(relative_path)
+                    assert file_id is not None
+                    tt.version_file(file_id, trans_id)
+                    found = True
+                    break
+            if not found:
                 tt.version_file(trans_id, trans_id)
         added.add(relative_path)
 
@@ -288,7 +297,7 @@
                                  make_upstream_tag(last_upstream))
         tree.revert(None,
                     tree.branch.repository.revision_tree(old_upstream_revid))
-      import_tar(tree, f, file_ids_from=dangling_tree)
+      import_tar(tree, f, file_ids_from=[dangling_tree])
       if last_upstream is not None:
         tree.set_parent_ids([old_upstream_revid])
         revno = tree.branch.revision_id_to_revno(old_upstream_revid)
@@ -318,7 +327,7 @@
           dangling_tree = tree.branch.repository.revision_tree(dangling_revid)
         tree.revert(None,
                     tree.branch.repository.revision_tree(old_upstream_revid))
-      import_tar(tree, f, file_ids_from=dangling_tree)
+      import_tar(tree, f, file_ids_from=[dangling_tree])
       if last_upstream is not None:
         tree.set_parent_ids([old_upstream_revid])
         revno = tree.branch.revision_id_to_revno(old_upstream_revid)
@@ -882,6 +891,16 @@
         """
         self.get_greater_branches = callback
 
+    def get_other_branches(self):
+        """Return all the other branches in this set.
+
+        The returned list will be ordered, and will not contain this
+        branch.
+
+        :return: a list of all the other branches in this set (if any).
+        """
+        return self.get_lesser_branches() + self.get_greater_branches()
+
     def tag_name(self, version):
         """Gets the name of the tag that is used for the version.
 
@@ -1334,8 +1353,10 @@
         mutter("Importing upstream version %s from %s" \
                 % (version, upstream_filename))
         tar_input = open(upstream_filename, 'rb')
+        other_branches = self.get_other_branches()
+        upstream_trees = [o.upstream_tree for o in other_branches]
         import_tar(self.upstream_tree, tar_input,
-                file_ids_from=self.upstream_tree)
+                file_ids_from=upstream_trees + [self.tree])
         revid = self.upstream_tree.commit("Import upstream from %s" \
                 % (osutils.basename(upstream_filename),),
                 revprops={"deb-md5":md5})
@@ -1343,7 +1364,7 @@
         self.tree.branch.fetch(self.upstream_tree.branch,
                 last_revision=revid)
 
-    def _import_patch(self, diff_filename, parents):
+    def _import_patch(self, diff_filename, parents, file_ids_from=None):
         """Apply a patch and update the tree to match.
 
         This applies the patch from diff_filename to self.tree, and
@@ -1359,7 +1380,7 @@
         try:
             tp = TreePatcher(self.tree)
             tp.set_patch_from_fileobj(f)
-            tp.patch_tree(parents)
+            tp.patch_tree(parents, file_ids_from=file_ids_from)
         finally:
             f.close()
 
@@ -1417,7 +1438,10 @@
         self.tree.revert(None,
                 self.upstream_tree.branch.repository.revision_tree(
                     upstream_revid))
-        self._import_patch(diff_filename, parents)
+        other_branches = self.get_other_branches()
+        debian_trees = [o.tree for o in other_branches]
+        self._import_patch(diff_filename, parents,
+                file_ids_from=debian_trees)
         rules_path = os.path.join(self.tree.basedir, 'debian', 'rules')
         if os.path.isfile(rules_path):
             os.chmod(rules_path,

=== modified file 'tests/test_import_dsc.py'
--- a/tests/test_import_dsc.py	2008-06-04 10:08:21 +0000
+++ b/tests/test_import_dsc.py	2008-06-10 13:13:04 +0000
@@ -1932,6 +1932,34 @@
         self.assertEqual(self.db2.revid_of_upstream_version(version),
                 up_revid)
 
+    def check_changes(self, changes, added=[], removed=[], modified=[],
+                      renamed=[]):
+        def check_one_type(type, expected, actual):
+            def make_set(list):
+                output = set()
+                for item in list:
+                    if item[2] == 'directory':
+                        output.add(item[0] + '/')
+                    else:
+                        output.add(item[0])
+                return output
+            exp = set(expected)
+            real = make_set(actual)
+            missing = exp.difference(real)
+            extra = real.difference(exp)
+            if len(missing) > 0:
+                self.fail("Some expected paths not found %s in the changes: "
+                          "%s, expected %s, got %s." % (type, str(missing),
+                              str(expected), str(actual)))
+            if len(extra) > 0:
+                self.fail("Some extra paths found %s in the changes: "
+                          "%s, expected %s, got %s." % (type, str(extra),
+                              str(expected), str(actual)))
+        check_one_type("added", added, changes.added)
+        check_one_type("removed", removed, changes.removed)
+        check_one_type("modified", modified, changes.modified)
+        check_one_type("renamed", renamed, changes.renamed)
+
     def test_import_upstream(self):
         version = Version("0.1-1")
         name = "package"
@@ -1951,11 +1979,45 @@
                 "Import upstream from %s" % builder.orig_name())
         self.assertEqual(rev.properties['deb-md5'], self.fake_md5_1)
 
+    def test_import_upstream_on_another(self):
+        version1 = Version("0.1-1")
+        version2 = Version("0.1-2")
+        name = "package"
+        builder = SourcePackageBuilder(name, version1)
+        builder.add_upstream_file("README", "Hi\n")
+        builder.add_upstream_file("BUGS")
+        builder.add_upstream_file("COPYING")
+        builder.build_orig()
+        self.db1.import_upstream(builder.orig_name(), version1,
+                self.fake_md5_1)
+        builder = SourcePackageBuilder(name, version2)
+        builder.add_upstream_file("README", "Now even better\n")
+        builder.add_upstream_file("BUGS")
+        builder.add_upstream_file("NEWS")
+        builder.build_orig()
+        self.db1.import_upstream(builder.orig_name(), version2,
+                self.fake_md5_2)
+        tree = self.up_tree1
+        branch = tree.branch
+        rh = branch.revision_history()
+        self.assertEqual(len(rh), 2)
+        self.assertEqual(self.db1.revid_of_upstream_version(version2), rh[1])
+        rev = branch.repository.get_revision(rh[1])
+        self.assertEqual(rev.message,
+                "Import upstream from %s" % builder.orig_name())
+        self.assertEqual(rev.properties['deb-md5'], self.fake_md5_2)
+        rev_tree1 = branch.repository.revision_tree(rh[0])
+        rev_tree2 = branch.repository.revision_tree(rh[1])
+        changes = rev_tree2.changes_from(rev_tree1)
+        self.check_changes(changes, added=["NEWS"], removed=["COPYING"],
+                modified=["README"])
+
     def test_import_package_init_from_other(self):
         version1 = Version("0.1-1")
         version2 = Version("0.2-1")
         up_revid1 = self.up_tree1.commit("upstream one")
         self.db1.tag_upstream_version(version1)
+        self.tree1.pull(self.up_tree1.branch)
         revid1 = self.tree1.commit("one")
         self.db1.tag_version(version1)
         builder = SourcePackageBuilder("package", version2)
@@ -1974,6 +2036,7 @@
         builder.build()
         self.db2.import_package(builder.dsc_name())
         self.assertEqual(len(self.up_tree2.branch.revision_history()), 2)
+        self.assertEqual(len(self.tree2.branch.revision_history()), 3)
 
     def import_package_single(self):
         version1 = Version("0.1-1")
@@ -1988,6 +2051,120 @@
         builder.add_debian_file("debian/changelog", str(cl))
         builder.build()
         self.db1.import_package(builder.dsc_name())
+        self.assertEqual(len(self.up_tree1.branch.revision_history()), 1)
+        self.assertEqual(len(self.tree1.branch.revision_history()), 2)
+
+    def test_import_package_double(self):
+        version1 = Version("0.1-1")
+        version2 = Version("0.2-1")
+        builder = SourcePackageBuilder("package", version1)
+        cl = Changelog()
+        cl.new_block(package="package", version=version1,
+                distributions="unstable", urgency="low",
+                author="Maint <maint at maint.org",
+                date="Wed, 19 Mar 2008 21:27:37 +0000")
+        cl.add_change("  * foo")
+        builder.add_upstream_file("README", "foo")
+        builder.add_upstream_file("BUGS")
+        builder.add_upstream_file("NEWS")
+        builder.add_debian_file("debian/changelog", str(cl))
+        builder.add_debian_file("COPYING", "Don't do it\n")
+        builder.build()
+        self.db1.import_package(builder.dsc_name())
+        cl.new_block(package="package", version=version2,
+                distributions="unstable", urgency="low",
+                author="Maint <maint at maint.org",
+                date="Wed, 19 Mar 2008 21:27:37 +0000")
+        cl.add_change("  * foo")
+        builder = SourcePackageBuilder("package", version2)
+        builder.add_upstream_file("README", "bar")
+        builder.add_upstream_file("BUGS")
+        builder.add_upstream_file("COPYING", "Please do\n")
+        builder.add_upstream_file("src.c")
+        builder.add_debian_file("debian/changelog", str(cl))
+        builder.build()
+        self.db1.import_package(builder.dsc_name())
+        rh = self.tree1.branch.revision_history()
+        up_rh = self.up_tree1.branch.revision_history()
+        self.assertEqual(len(up_rh), 2)
+        self.assertEqual(len(rh), 3)
+        self.assertEqual(rh[0], up_rh[0])
+        self.assertNotEqual(rh[1], up_rh[1])
+        # Check the parents are correct.
+        rev_tree1 = self.tree1.branch.repository.revision_tree(rh[1])
+        rev_tree2 = self.tree1.branch.repository.revision_tree(rh[2])
+        up_rev_tree1 = self.up_tree1.branch.repository.revision_tree(up_rh[0])
+        up_rev_tree2 = self.up_tree1.branch.repository.revision_tree(up_rh[1])
+        self.assertEqual(up_rev_tree1.get_parent_ids(), [])
+        self.assertEqual(up_rev_tree2.get_parent_ids(), [up_rh[0]])
+        self.assertEqual(rev_tree1.get_parent_ids(), [up_rh[0]])
+        self.assertEqual(rev_tree2.get_parent_ids(), [rh[1], up_rh[1]])
+        # Check that the file ids are correct.
+        self.check_changes(up_rev_tree2.changes_from(up_rev_tree1),
+                added=["COPYING", "src.c"], removed=["NEWS"],
+                modified=["README"])
+        self.check_changes(rev_tree1.changes_from(up_rev_tree1),
+                added=["debian/", "debian/changelog", "COPYING"])
+        self.check_changes(rev_tree2.changes_from(rev_tree1),
+                modified=["debian/changelog", "COPYING", "README"],
+                added=["src.c"], removed=["NEWS"])
+        self.check_changes(rev_tree2.changes_from(up_rev_tree2),
+                added=["debian/", "debian/changelog"])
+        self.check_changes(up_rev_tree2.changes_from(rev_tree1),
+                added=["src.c"],
+                removed=["NEWS", "debian/", "debian/changelog"],
+                modified=["README", "COPYING"])
+
+    def test_import_two_roots(self):
+        version1 = Version("0.1-0ubuntu1")
+        version2 = Version("0.1-1")
+        builder = SourcePackageBuilder("package", version1)
+        cl = Changelog()
+        cl.new_block(package="package", version=version1,
+                distributions="intrepid", urgency="low",
+                author="Maint <maint at maint.org",
+                date="Wed, 19 Mar 2008 21:27:37 +0000")
+        cl.add_change("  * foo")
+        builder.add_upstream_file("README", "foo")
+        builder.add_debian_file("debian/changelog", str(cl))
+        builder.build()
+        self.db2.import_package(builder.dsc_name())
+        cl = Changelog()
+        cl.new_block(package="package", version=version2,
+                distributions="unstable", urgency="low",
+                author="Maint <maint at maint.org",
+                date="Wed, 19 Mar 2008 21:27:37 +0000")
+        cl.add_change("  * foo")
+        builder = SourcePackageBuilder("package", version2)
+        builder.add_upstream_file("README", "bar")
+        builder.add_debian_file("debian/changelog", str(cl))
+        builder.build()
+        self.db1.import_package(builder.dsc_name())
+        rh1 = self.tree1.branch.revision_history()
+        rh2 = self.tree2.branch.revision_history()
+        up_rh1 = self.up_tree1.branch.revision_history()
+        up_rh2 = self.up_tree2.branch.revision_history()
+        self.assertEqual(len(rh1), 2)
+        self.assertEqual(len(rh2), 2)
+        self.assertEqual(len(up_rh1), 1)
+        self.assertEqual(len(up_rh2), 1)
+        self.assertNotEqual(rh1, rh2)
+        self.assertNotEqual(rh1[0], rh2[0])
+        self.assertNotEqual(rh1[1], rh2[1])
+        self.assertEqual(rh1[0], up_rh1[0])
+        self.assertEqual(rh2[0], up_rh2[0])
+        rev_tree1 = self.tree1.branch.repository.revision_tree(rh1[1])
+        rev_tree2 = self.tree2.branch.repository.revision_tree(rh2[1])
+        up_rev_tree1 = self.up_tree1.branch.repository.revision_tree(rh1[0])
+        up_rev_tree2 = self.up_tree2.branch.repository.revision_tree(rh2[0])
+        self.check_changes(rev_tree1.changes_from(up_rev_tree1),
+                added=["debian/", "debian/changelog"])
+        self.check_changes(rev_tree2.changes_from(up_rev_tree2),
+                added=["debian/", "debian/changelog"])
+        self.check_changes(rev_tree2.changes_from(rev_tree1),
+                modified=["README", "debian/changelog"])
+        self.check_changes(up_rev_tree2.changes_from(up_rev_tree1),
+                modified=["README"])
 
 
 class SourcePackageBuilder(object):
@@ -2036,19 +2213,24 @@
     def basedir(self):
         return self.name + "-" + str(self.version.upstream_version)
 
-    def build_orig(self):
+    def _make_base(self):
         basedir = self.basedir()
         os.mkdir(basedir)
         self._make_files(self.upstream_files, basedir)
+        return basedir
+
+    def build_orig(self):
+        basedir = self._make_base()
         tar = tarfile.open(self.orig_name(), 'w:gz')
         try:
           tar.add(basedir)
         finally:
           tar.close()
+        shutil.rmtree(basedir)
 
     def build(self):
-        basedir = self.basedir()
         self.build_orig()
+        basedir = self._make_base()
         orig_basedir = basedir + ".orig"
         shutil.copytree(basedir, orig_basedir)
         self._make_files(self.debian_files, basedir)

=== modified file 'tree_patcher.py'
--- a/tree_patcher.py	2008-06-04 10:08:21 +0000
+++ b/tree_patcher.py	2008-06-10 13:13:04 +0000
@@ -115,7 +115,7 @@
             raise BzrError('lsdiff failed')
         return touched_paths
 
-    def _update_path(self, path, parent_trees):
+    def _update_path(self, path, parent_trees, file_ids_from):
         """You probably want _update_path_info instead."""
         tree = self.tree
         # If tree doesn't have it then it was removed.
@@ -130,12 +130,20 @@
             file_id = parent_tree.path2id(path)
             if file_id is not None:
                 tree.add([path], [file_id])
+                added = True
                 break
         if not added:
+            for other_tree in file_ids_from:
+                file_id = other_tree.path2id(path)
+                if file_id is not None:
+                    tree.add([path], [file_id])
+                    added = True
+                    break
+        if not added:
             # New file that didn't exist in any parent, just add it
             tree.add([path])
 
-    def _update_path_info(self, touched_paths, parents):
+    def _update_path_info(self, touched_paths, parents, file_ids_from=None):
         """Update the working tree to reflect the changes in certain paths.
 
         Given a list of paths this method will update the working tree
@@ -148,6 +156,8 @@
         :param parents: a list of revision ids that should be used
             for working out whether a path needs modification.
         """
+        if file_ids_from is None:
+            file_ids_from = []
         tree = self.tree
         def get_tree(parent):
             return tree.branch.repository.revision_tree(parent)
@@ -162,10 +172,10 @@
                     base_path = os.path.join(base_path, part)
                 if base_path in checked_paths:
                     continue
-                self._update_path(base_path, parent_trees)
+                self._update_path(base_path, parent_trees, file_ids_from)
                 checked_paths.add(base_path)
 
-    def patch_tree(self, parents):
+    def patch_tree(self, parents, file_ids_from=None):
         """Patch the tree with the supplied patch file.
 
         :param parents: a list of parent ids to take the file ids from
@@ -175,6 +185,7 @@
         self._patch_tree(self.patch, self.tree.basedir)
         self.patch.seek(0)
         touched_paths = self._get_touched_paths(self.patch)
-        self._update_path_info(touched_paths, parents)
+        self._update_path_info(touched_paths, parents,
+                file_ids_from=file_ids_from)
 
 



More information about the Pkg-bazaar-commits mailing list