[Pkg-bazaar-commits] ./bzr-builddeb/trunk.old r232: Use dpkg-source to extract the source packages and then import from that.

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


------------------------------------------------------------
revno: 232
committer: James Westby <jw+debian at jameswestby.net>
branch nick: import
timestamp: Wed 2008-06-11 13:13:49 +0100
message:
  Use dpkg-source to extract the source packages and then import from that.
  
  This should be much more robust, and means that we can import both upstream
  and debianised parts using the same code path.
  
  This means the TreePatcher can die, and we no longer have the ugly and
  fragile hack to read the changelog from the .diff.gz.
  
  The only downside is that we would now want a dpkg-source to be available
  that was backed by the bzr VFS so that we can avoid having to bring files
  to disk, but this isn't a great loss.
removed:
  tests/test_tree_patcher.py
  tree_patcher.py
modified:
  import_dsc.py
  tests/test_import_dsc.py
-------------- next part --------------
=== modified file 'import_dsc.py'
--- a/import_dsc.py	2008-06-10 16:07:55 +0000
+++ b/import_dsc.py	2008-06-11 12:13:49 +0000
@@ -27,9 +27,12 @@
 import gzip
 import os
 import select
+import shutil
 import stat
 from subprocess import Popen, PIPE
+from StringIO import StringIO
 import tarfile
+import tempfile
 
 from debian_bundle import deb822
 from debian_bundle.changelog import Version, Changelog
@@ -63,11 +66,20 @@
 from bzrlib.plugins.builddeb.merge_upstream import (make_upstream_tag,
                 upstream_tag_to_version,
                 )
-from bzrlib.plugins.builddeb.tree_patcher import (
-        TreePatcher,
-        files_to_ignore,
-        ignore_arguments,
-        )
+
+
+files_to_ignore = set(['.cvsignore', '.arch-inventory', '.bzrignore',
+    '.gitignore', 'CVS', 'RCS', '.deps', '{arch}', '.arch-ids', '.svn',
+    '.hg', '_darcs', '.git', '.shelf', '.bzr', '.bzr.backup', '.bzrtags',
+    '.bzr-builddeb'])
+
+exclude_as_files = ['*/' + x for x in files_to_ignore]
+exclude_as_dirs = ['*/' + x + '/*' for x in files_to_ignore]
+exclude = exclude_as_files + exclude_as_dirs
+underscore_x = ['-x'] * len(exclude)
+ignore_arguments = []
+map(ignore_arguments.extend, zip(underscore_x, exclude))
+ignore_arguments = ignore_arguments + ['-x', '*,v']
 
 
 def import_tar(tree, tar_input, file_ids_from=None):
@@ -78,6 +90,76 @@
     import_archive(tree, tar_file, file_ids_from=file_ids_from)
 
 
+class DirWrapper(object):
+    def __init__(self, fileobj, mode='r'):
+        assert mode == 'r', mode
+        self.root = os.path.realpath(fileobj.read())
+
+    def __repr__(self):
+        return 'DirWrapper(%r)' % self.root
+
+    def getmembers(self, subdir=None):
+        if subdir is not None:
+            mydir = os.path.join(self.root, subdir)
+        else:
+            mydir = self.root
+        for child in os.listdir(mydir):
+            if subdir is not None:
+                child = os.path.join(subdir, child)
+            fi = FileInfo(self.root, child)
+            yield fi
+            if fi.isdir():
+                for v in self.getmembers(child):
+                    yield v
+
+    def extractfile(self, member):
+        return open(member.fullpath)
+
+
+class FileInfo(object):
+
+    def __init__(self, root, filepath):
+        self.fullpath = os.path.join(root, filepath)
+        self.root = root
+        if filepath != '':
+            self.name = os.path.join(basename(root), filepath)
+        else:
+            print 'root %r' % root
+            self.name = basename(root)
+        self.type = None
+        stat = os.lstat(self.fullpath)
+        self.mode = stat.st_mode
+        if self.isdir():
+            self.name += '/'
+
+    def __repr__(self):
+        return 'FileInfo(%r)' % self.name
+
+    def isreg(self):
+        return stat.S_ISREG(self.mode)
+
+    def isdir(self):
+        return stat.S_ISDIR(self.mode)
+
+    def issym(self):
+        if stat.S_ISLNK(self.mode):
+            self.linkname = os.readlink(self.fullpath)
+            return True
+        else:
+            return False
+
+    def islnk(self):
+        # This could be accurate, but the use below seems like
+        # it wouldn't really care
+        return False
+
+
+def import_dir(tree, dir, file_ids_from=None):
+    dir_input = StringIO(dir)
+    dir_file = DirWrapper(dir_input)
+    import_archive(tree, dir_file, file_ids_from=file_ids_from)
+
+
 def do_directory(tt, trans_id, tree, relative_path, path):
     if isdir(path) and tree.path2id(relative_path) is not None:
         tt.cancel_deletion(trans_id)
@@ -1339,15 +1421,14 @@
                 real_parents = [parent_revid]
         return real_parents
 
-    def import_upstream(self, upstream_filename, version, md5):
+    def import_upstream(self, upstream_part, version, md5):
         """Import an upstream part on to the upstream branch.
 
-        This imports the upstream part of the code from the .orig.tar.gz
-        and places it on to the upstream branch, setting the necessary
-        tags.
+        This imports the upstream part of the code and places it on to
+        the upstream branch, setting the necessary tags.
 
-        :param upstream_filename: the path of the upstream part of
-            the package, i.e. the .orig.tar.gz.
+        :param upstream_part: the path of a directory containing the
+            unpacked upstream part of the source package.
         :param version: the Version of the package that is being imported.
         """
         # Should we just dump the upstream part on whatever is currently
@@ -1355,41 +1436,19 @@
         # from lesser branches first? For now we'll just dump it on.
         # TODO: this method needs a lot of work for when we will make
         # the branches writeable by others.
-        # TODO: check md5 matches upstream_filename
         mutter("Importing upstream version %s from %s" \
-                % (version, upstream_filename))
-        tar_input = open(upstream_filename, 'rb')
+                % (version, upstream_part))
         other_branches = self.get_other_branches()
         upstream_trees = [o.upstream_tree for o in other_branches]
-        import_tar(self.upstream_tree, tar_input,
+        import_dir(self.upstream_tree, upstream_part,
                 file_ids_from=upstream_trees + [self.tree])
-        revid = self.upstream_tree.commit("Import upstream from %s" \
-                % (osutils.basename(upstream_filename),),
+        revid = self.upstream_tree.commit("Import upstream version %s" \
+                % (str(version.upstream_version),),
                 revprops={"deb-md5":md5})
         self.tag_upstream_version(version)
         self.tree.branch.fetch(self.upstream_tree.branch,
                 last_revision=revid)
 
-    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
-        then performs adds and removes in the working tree as necessary,
-        depending on what the patch did.
-
-        :param diff_filename: the filename of the the file containing the
-            diff in gzip compressed form.
-        :param parents: the list of parents that will be used when the
-            result is committed.
-        """
-        f = gzip.GzipFile(diff_filename)
-        try:
-            tp = TreePatcher(self.tree)
-            tp.set_patch_from_fileobj(f)
-            tp.patch_tree(parents, file_ids_from=file_ids_from)
-        finally:
-            f.close()
-
     def _get_commit_message_from_changelog(self):
         """Retrieves the messages from the last section of debian/changelog.
 
@@ -1417,20 +1476,19 @@
               sep = "\n"
         return (message, author)
 
-    def import_diff(self, diff_filename, version, parents, md5):
-        """Import the diff part of a source package.
+    def import_debian(self, debian_part, version, parents, md5):
+        """Import the debian part of a source package.
 
-        :param diff_filename: a filename of a gzip compressed patch
-            to the corresponding upstream version.
-        :param version: the Version that this diff corresponds to.
+        :param debian_part: the path of a directory containing the unpacked
+            source package.
+        :param version: the Version of the source package.
         :param parents: a list of revision ids that should be the
             parents of the imported revision.
         :param md5: the md5 sum reported by the .dsc for
-            diff_filename.
+            the .diff.gz part of this source package.
         """
-        mutter("Importing diff part for version %s from %s, with parents "
-                "%s" % (str(version), diff_filename, str(parents)))
-        # TODO: check md5 matches the md5 of diff_filename
+        mutter("Importing debian part for version %s from %s, with parents "
+                "%s" % (str(version), debian_part, str(parents)))
         # First we move the branch to the first parent
         if parents:
             parent_revid = parents[0]
@@ -1438,16 +1496,14 @@
             parent_revid = NULL_REVISION
         self.tree.pull(self.tree.branch, overwrite=True,
                 stop_revision=parent_revid)
-        # Then we revert the tree to the upstream code, as that is
-        # what the patch applies to.
-        upstream_revid = self.revid_of_upstream_version(version)
-        self.tree.revert(None,
-                self.upstream_tree.branch.repository.revision_tree(
-                    upstream_revid))
         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)
+        parent_trees = []
+        for parent in parents:
+            parent_trees.append(self.tree.branch.repository.revision_tree(
+                        parent))
+        import_dir(self.tree, debian_part,
+                file_ids_from=parent_trees + debian_trees)
         rules_path = os.path.join(self.tree.basedir, 'debian', 'rules')
         if os.path.isfile(rules_path):
             os.chmod(rules_path,
@@ -1456,27 +1512,11 @@
         self.tree.set_parent_ids(parents)
         (message, author) = self._get_commit_message_from_changelog()
         if message is None:
-            message = 'merge packaging changes from %s' % \
-                        (os.path.basename(diff_filename))
+            message = 'Import packaging changes for version %s' % \
+                        (str(version),)
         self.tree.commit(message, author=author, revprops={"deb-md5":md5})
         self.tag_version(version)
 
-    def _get_changelog_from_diff(self, diff_filename):
-        """Don't look, it's too horrible."""
-        cmd = ['filterdiff', '-i', '*/debian/changelog', '-z',
-             diff_filename]
-        child_proc = Popen(cmd, stdout=PIPE, close_fds=True)
-        output = ''
-        for line in child_proc.stdout.readlines():
-            if line.startswith("---"):
-                continue
-            if line.startswith("+++"):
-                continue
-            if line.startswith("@@"):
-                continue
-            output += line[1:]
-        return output
-
     def _get_dsc_part(self, dsc, end):
         """Get the path and md5 of a file ending with end in dsc."""
         files = dsc['files']
@@ -1522,31 +1562,25 @@
             self.upstream_tree.pull(up_pull_branch,
                     stop_revision=pull_revid)
 
-    def import_package(self, dsc_filename):
-        """Import a source package.
-
-        :param dsc_filename: a path to a .dsc file for the version
-            to be imported.
-        """
-        base_path = osutils.dirname(dsc_filename)
-        dsc = deb822.Dsc(open(dsc_filename).read())
-        version = Version(dsc['Version'])
-        # TODO: check files make sense (no two .orig or similar)
-        (upstream_part, upstream_md5) = self.get_upstream_part(dsc)
-        (diff_filename, md5) = self.get_diff_part(dsc)
-        assert diff_filename is not None
-        assert upstream_part is not None
-        diff_filename = os.path.join(base_path, diff_filename)
-        upstream_part = os.path.join(base_path, upstream_part)
-        cl_text = self._get_changelog_from_diff(diff_filename)
+    def get_changelog_from_source(self, dir):
+        cl_filename = os.path.join(dir, "debian", "changelog")
         cl = Changelog()
-        cl.parse_changelog(cl_text)
-        versions = cl.versions
-        assert not self.has_version(version), \
-            "Trying to import version %s again" % str(version)
-        #TODO: check that the versions list is correctly ordered,
-        # as some methods assume that, and it's not clear what
-        # should happen if it isn't.
+        cl.parse_changelog(open(cl_filename).read())
+        return cl
+
+    def extract_dsc(self, dsc_filename):
+        """Extract a dsc file in to a temporary directory."""
+        tempdir = tempfile.mkdtemp()
+        dsc_filename = os.path.abspath(dsc_filename)
+        proc = Popen("dpkg-source -su -x %s" % (dsc_filename,), shell=True,
+                cwd=tempdir, stdout=PIPE, stderr=PIPE)
+        ret = proc.wait()
+        assert ret == 0, "dpkg-source -x failed, output:\n%s\n%s" % \
+                    (proc.stdout.read(), proc.stderr.read())
+        return tempdir
+
+    def _do_import_package(self, version, versions, debian_part, md5,
+            upstream_part, upstream_md5):
         pull_branch = self.branch_to_pull_version_from(version, md5)
         if pull_branch is not None:
             self.pull_version_from_branch(pull_branch, version)
@@ -1573,5 +1607,37 @@
             parents = self.get_parents_with_upstream(version, versions,
                     force_upstream_parent=imported_upstream)
             # Now we have the list of parents we need to import the .diff.gz
-            self.import_diff(diff_filename, version, parents, md5)
+            self.import_debian(debian_part, version, parents, md5)
+
+    def import_package(self, dsc_filename):
+        """Import a source package.
+
+        :param dsc_filename: a path to a .dsc file for the version
+            to be imported.
+        """
+        base_path = osutils.dirname(dsc_filename)
+        dsc = deb822.Dsc(open(dsc_filename).read())
+        version = Version(dsc['Version'])
+        name = dsc['Source']
+        tempdir = self.extract_dsc(dsc_filename)
+        try:
+            # TODO: make more robust against strange .dsc files.
+            (upstream_part, upstream_md5) = self.get_upstream_part(dsc)
+            (diff_filename, md5) = self.get_diff_part(dsc)
+            upstream_part = os.path.join(tempdir,
+                    "%s-%s.orig" % (name, str(version.upstream_version)))
+            debian_part = os.path.join(tempdir,
+                    "%s-%s" % (name, str(version.upstream_version)))
+            assert os.path.exists(upstream_part)
+            cl = self.get_changelog_from_source(debian_part)
+            versions = cl.versions
+            assert not self.has_version(version), \
+                "Trying to import version %s again" % str(version)
+            #TODO: check that the versions list is correctly ordered,
+            # as some methods assume that, and it's not clear what
+            # should happen if it isn't.
+            self._do_import_package(version, versions, debian_part, md5,
+                    upstream_part, upstream_md5)
+        finally:
+            shutil.rmtree(tempdir)
 

=== modified file 'tests/test_import_dsc.py'
--- a/tests/test_import_dsc.py	2008-06-10 16:08:25 +0000
+++ b/tests/test_import_dsc.py	2008-06-11 12:13:49 +0000
@@ -1934,6 +1934,34 @@
         self.assertEqual(self.db2.revid_of_upstream_version(version),
                 up_revid)
 
+    def test_extract_dsc(self):
+        version = Version("0.1-1")
+        name = "package"
+        builder = SourcePackageBuilder(name, version)
+        builder.add_upstream_file("README", "Hi\n")
+        builder.add_upstream_file("BUGS")
+        builder.add_default_changelog()
+        builder.add_default_control()
+        builder.build()
+        tempdir = self.db1.extract_dsc(builder.dsc_name())
+        self.assertTrue(os.path.exists(tempdir))
+        try:
+            unpacked_dir = os.path.join(tempdir,
+                            name+"-"+str(version.upstream_version))
+            orig_dir = unpacked_dir + ".orig"
+            self.assertTrue(os.path.exists(unpacked_dir))
+            self.assertTrue(os.path.exists(orig_dir))
+            self.assertTrue(os.path.exists(os.path.join(unpacked_dir,
+                            "README")))
+            self.assertTrue(os.path.exists(os.path.join(unpacked_dir,
+                            "debian", "control")))
+            self.assertTrue(os.path.exists(os.path.join(orig_dir,
+                            "README")))
+            self.assertFalse(os.path.exists(os.path.join(orig_dir,
+                            "debian", "control")))
+        finally:
+            shutil.rmtree(tempdir)
+
     def check_changes(self, changes, added=[], removed=[], modified=[],
                       renamed=[]):
         def check_one_type(type, expected, actual):
@@ -1965,14 +1993,11 @@
     def test_import_upstream(self):
         version = Version("0.1-1")
         name = "package"
-        builder = SourcePackageBuilder(name, version)
-        builder.add_upstream_file("README", "Hi\n")
-        builder.add_upstream_file("BUGS")
-        builder.add_default_changelog()
-        builder.add_default_control()
-        builder.build()
-        self.db1.import_upstream(builder.orig_name(), version,
-                self.fake_md5_1)
+        basedir = name + "-" + str(version.upstream_version)
+        os.mkdir(basedir)
+        write_to_file(os.path.join(basedir, "README"), "Hi\n")
+        write_to_file(os.path.join(basedir, "BUGS"), "")
+        self.db1.import_upstream(basedir, version, self.fake_md5_1)
         tree = self.up_tree1
         branch = tree.branch
         rh = branch.revision_history()
@@ -1980,31 +2005,25 @@
         self.assertEqual(self.db1.revid_of_upstream_version(version), rh[0])
         rev = branch.repository.get_revision(rh[0])
         self.assertEqual(rev.message,
-                "Import upstream from %s" % builder.orig_name())
+                "Import upstream version %s" % str(version.upstream_version))
         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.2-1")
         name = "package"
-        builder = SourcePackageBuilder(name, version1)
-        builder.add_upstream_file("README", "Hi\n")
-        builder.add_upstream_file("BUGS")
-        builder.add_upstream_file("COPYING")
-        builder.add_default_changelog()
-        builder.add_default_control()
-        builder.build()
-        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.add_default_changelog()
-        builder.add_default_control()
-        builder.build()
-        self.db1.import_upstream(builder.orig_name(), version2,
-                self.fake_md5_2)
+        basedir = name + "-" + str(version1.upstream_version)
+        os.mkdir(basedir)
+        write_to_file(os.path.join(basedir, "README"), "Hi\n")
+        write_to_file(os.path.join(basedir, "BUGS"), "")
+        write_to_file(os.path.join(basedir, "COPYING"), "")
+        self.db1.import_upstream(basedir, version1, self.fake_md5_1)
+        basedir = name + "-" + str(version2.upstream_version)
+        os.mkdir(basedir)
+        write_to_file(os.path.join(basedir, "README"), "Now even better\n")
+        write_to_file(os.path.join(basedir, "BUGS"), "")
+        write_to_file(os.path.join(basedir, "NEWS"), "")
+        self.db1.import_upstream(basedir, version2, self.fake_md5_2)
         tree = self.up_tree1
         branch = tree.branch
         rh = branch.revision_history()
@@ -2012,7 +2031,7 @@
         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())
+                "Import upstream version %s" % str(version2.upstream_version))
         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])

=== removed file 'tests/test_tree_patcher.py'
--- a/tests/test_tree_patcher.py	2008-06-04 10:08:21 +0000
+++ b/tests/test_tree_patcher.py	1970-01-01 00:00:00 +0000
@@ -1,173 +0,0 @@
-#    test_tree_patcher.py -- Tests for the TreePatcher.
-#    Copyright (C) 2008 Canonical Limited.
-#
-#    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
-
-from bzrlib.tests import TestCaseWithTransport
-
-from bzrlib.plugins.builddeb.tree_patcher import TreePatcher
-
-
-def write_to_file(filename, contents):
-  f = open(filename, 'wb')
-  try:
-    f.write(contents)
-  finally:
-    f.close()
-
-
-class TreePatcherTests(TestCaseWithTransport):
-
-    def assertContentsAre(self, filename, expected_contents):
-        f = open(filename)
-        try:
-          contents = f.read()
-        finally:
-          f.close()
-        self.assertEqual(contents, expected_contents,
-                         "Contents of %s are not as expected" % filename)
-
-    def make_simple_patch_base(self):
-        basedir = "base"
-        os.mkdir(basedir)
-        write_to_file(os.path.join(basedir, "a"), "a\na\na\n")
-        write_to_file(os.path.join(basedir, "b"), "b\nb\nb\n")
-        write_to_file(os.path.join(basedir, "c"), "c\nc\nc\n")
-        write_to_file(os.path.join(basedir, "d"), "d\nd\nd\n")
-        write_to_file(os.path.join(basedir, "e"), "")
-        write_to_file(os.path.join(basedir, ".bzr"), "a\na\na\n")
-
-    def test__patch_tree(self):
-        tree = self.make_simple_patch_base()
-        tp = TreePatcher(tree)
-        tp._patch_tree(simple_test_patch, "base")
-        self.failIfExists("base/a")
-        self.assertContentsAre("base/b", "")
-        self.assertContentsAre("base/c", "c\n")
-        self.assertContentsAre("base/d", "d\nd\nd\nd\n")
-        self.assertContentsAre("base/e", "e\ne\ne\n")
-        self.assertContentsAre("base/f", "f\nf\nf\n")
-        # .bzr and .git shouldn't be changed
-        self.assertContentsAre("base/.bzr", "a\na\na\n")
-        self.failIfExists("base/.git")
-
-    def test__get_touched_paths(self):
-        tree = self.make_simple_patch_base()
-        tp = TreePatcher(tree)
-        touched_paths = tp._get_touched_paths(simple_test_patch)
-        self.assertEqual(touched_paths, ["a", "b", "c", "d", "e", "f"])
-
-    def test__update_path_info(self):
-        tree = self.make_branch_and_tree(".")
-        os.mkdir("base")
-        write_to_file("a", "")
-        write_to_file("base/a", "")
-        tree.add(["a", "base", "base/a"], ["a-1", "base-1", "base-a-1"])
-        revid1 = tree.commit("one")
-        write_to_file("b", "")
-        write_to_file("base/b", "")
-        tree.remove(["base/a"])
-        tree.add(["b", "base/b"], ["b-2", "base-b-2"])
-        revid2 = tree.commit("two")
-        os.unlink("base/b")
-        os.mkdir("base2")
-        write_to_file("base2/c", "")
-        write_to_file("base/a", "")
-        tp = TreePatcher(tree)
-        tp._update_path_info(["base/b", "base2/c", "base/a", "b"],
-                [revid2, revid1])
-        self.assertNotEqual(tree.path2id("base2"), None)
-        self.assertNotEqual(tree.path2id("base2/c"), None)
-        self.assertEqual(tree.path2id("base/a"), "base-a-1")
-        self.assertEqual(tree.path2id("base/b"), None)
-        self.assertEqual(tree.path2id("a"), "a-1")
-        self.assertEqual(tree.path2id("b"), "b-2")
-
-    def test_patch_tree(self):
-        self.make_simple_patch_base()
-        os.unlink("base/.bzr")
-        tree = self.make_branch_and_tree('base')
-        tp = TreePatcher(tree)
-        tp.set_patch(simple_test_patch)
-        tp.patch_tree([])
-
-simple_test_patch_without_bzr = """diff -Nru base.old/a base/a
---- base.old/a  2008-05-14 19:53:53.000000000 +0100
-+++ base/a  1970-01-01 01:00:00.000000000 +0100
-@@ -1,3 +0,0 @@
--a
--a
--a
-diff -Nru base.old/b base/b
---- base.old/b  2008-05-14 19:53:53.000000000 +0100
-+++ base/b  2008-05-14 19:54:33.000000000 +0100
-@@ -1,3 +0,0 @@
--b
--b
--b
-diff -Nru base.old/c base/c
---- base.old/c  2008-05-14 19:53:53.000000000 +0100
-+++ base/c  2008-05-14 19:54:42.000000000 +0100
-@@ -1,3 +1,1 @@
- c
--c
--c
-diff -Nru base.old/d base/d
---- base.old/d  2008-05-14 19:53:53.000000000 +0100
-+++ base/d  2008-05-14 19:54:50.000000000 +0100
-@@ -1,3 +1,4 @@
- d
- d
- d
-+d
-diff -Nru base.old/e base/e
---- base.old/e  2008-05-14 19:53:53.000000000 +0100
-+++ base/e  2008-05-14 19:54:59.000000000 +0100
-@@ -0,0 +1,3 @@
-+e
-+e
-+e
-diff -Nru base.old/f base/f
---- base.old/f  1970-01-01 01:00:00.000000000 +0100
-+++ base/f  2008-05-14 19:55:06.000000000 +0100
-@@ -0,0 +1,3 @@
-+f
-+f
-+f
-diff -Nru base.old/.git base/.git
---- base.old/.git   1970-01-01 01:00:00.000000000 +0100
-+++ base/.git   2008-05-14 19:55:36.000000000 +0100
-@@ -0,0 +1,3 @@
-+a
-+a
-+a
-"""
-
-simple_test_patch = simple_test_patch_without_bzr + \
-"""diff -Nru base.old/.bzr base/.bzr
---- base.old/.bzr   2008-05-14 19:53:53.000000000 +0100
-+++ base/.bzr   2008-05-14 19:55:29.000000000 +0100
-@@ -1,3 +1,4 @@
- a
- a
- a
-+a
-"""
-

=== removed file 'tree_patcher.py'
--- a/tree_patcher.py	2008-06-10 13:13:04 +0000
+++ b/tree_patcher.py	1970-01-01 00:00:00 +0000
@@ -1,191 +0,0 @@
-#    tree_patcher.py -- Patch a working tree.
-#    Copyright (C) 2007 James Westby <jw+debian at jameswestby.net>
-#    Copyright (C) 2008 Canonical Limited.
-#
-#    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 cStringIO
-import os
-import select
-from subprocess import Popen, PIPE
-
-from bzrlib import osutils
-from bzrlib.errors import (
-        BzrError,
-        )
-
-
-files_to_ignore = set(['.cvsignore', '.arch-inventory', '.bzrignore',
-    '.gitignore', 'CVS', 'RCS', '.deps', '{arch}', '.arch-ids', '.svn',
-    '.hg', '_darcs', '.git', '.shelf', '.bzr', '.bzr.backup', '.bzrtags',
-    '.bzr-builddeb'])
-
-exclude_as_files = ['*/' + x for x in files_to_ignore]
-exclude_as_dirs = ['*/' + x + '/*' for x in files_to_ignore]
-exclude = exclude_as_files + exclude_as_dirs
-underscore_x = ['-x'] * len(exclude)
-ignore_arguments = []
-map(ignore_arguments.extend, zip(underscore_x, exclude))
-ignore_arguments = ignore_arguments + ['-x', '*,v']
-
-
-class TreePatcher(object):
-    """Patch a WorkingTree, including recording additions and removals."""
-
-    def __init__(self, tree):
-        """Create a TreePatcher to patch tree.
-
-        :param tree: the WorkingTree to act upon.
-        """
-        self.tree = tree
-        self.patch = None
-
-    def set_patch(self, patch):
-        """Set the patch to use from a String.
-
-        :param patch: the patch in the form of a string.
-        """
-        self.patch = cStringIO.StringIO(patch)
-
-    def set_patch_from_fileobj(self, fileobj):
-        """Set the patch from a file-like object.
-
-        :param fileobj: the file-like object to retrieve the patch from.
-        """
-        self.patch = fileobj
-
-    def _make_filter_proc(self):
-        """Create a filterdiff subprocess."""
-        filter_cmd = ['filterdiff'] + ignore_arguments
-        filter_proc = Popen(filter_cmd, stdin=PIPE, stdout=PIPE)
-        return filter_proc
-
-    def _patch_tree(self, patch, basedir):
-        """Patch a tree located at basedir."""
-        filter_proc = self._make_filter_proc()
-        patch_cmd = ['patch', '-g', '0', '--strip', '1', '--quiet', '-f',
-                     '--directory', basedir]
-        patch_proc = Popen(patch_cmd, stdin=filter_proc.stdout,
-                close_fds=True)
-        for line in patch:
-            filter_proc.stdin.write(line)
-            filter_proc.stdin.flush()
-        filter_proc.stdin.close()
-        r = patch_proc.wait()
-        if r != 0:
-            raise BzrError('patch failed')
-
-    def _get_touched_paths(self, patch):
-        """Return the list of paths that are touched by the patch."""
-        filter_proc = self._make_filter_proc()
-        cmd = ['lsdiff', '--strip', '1']
-        child_proc = Popen(cmd, stdin=filter_proc.stdout, stdout=PIPE,
-                           close_fds=True)
-        output = ''
-        for line in patch:
-            filter_proc.stdin.write(line)
-            filter_proc.stdin.flush()
-            while select.select([child_proc.stdout], [], [], 0)[0]:
-                output += child_proc.stdout.read(1)
-        filter_proc.stdin.close()
-        output += child_proc.stdout.read()
-        touched_paths = []
-        for filename in output.split('\n'):
-            if filename.endswith('\n'):
-                filename = filename[:-1]
-            if filename != "":
-                touched_paths.append(filename)
-        r = child_proc.wait()
-        if r != 0:
-            raise BzrError('lsdiff failed')
-        return touched_paths
-
-    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.
-        if not tree.has_filename(path):
-            tree.remove([path], verbose=False)
-            return
-        # Now look through the parents in order
-        # Give it the id of the first parent in which
-        # it is found.
-        added = False
-        for parent_tree in parent_trees:
-            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, 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
-        to reflect any adds/removes that occured in those paths when
-        compared to their parents.
-
-        :param tree: the WorkingTree in which to make the changes.
-        :param touched_paths: a list of paths for which to perform
-            any needed modifications.
-        :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)
-        parent_trees = [get_tree(p) for p in parents]
-        checked_paths = set()
-        for path in touched_paths:
-            base_path = None
-            for part in osutils.splitpath(path):
-                if base_path is None:
-                    base_path = part
-                else:
-                    base_path = os.path.join(base_path, part)
-                if base_path in checked_paths:
-                    continue
-                self._update_path(base_path, parent_trees, file_ids_from)
-                checked_paths.add(base_path)
-
-    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
-            for any added files.
-        """
-        assert self.patch is not None, "You must set the patch first"
-        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,
-                file_ids_from=file_ids_from)
-
-



More information about the Pkg-bazaar-commits mailing list