[Pkg-bazaar-commits] r127 ./bzr-builddeb/people/jdw/merge_upstream: Extend the import_dsc code to handle .dsc with no .orig.tar.gz.

James Westby jw+debian at jameswestby.net
Mon Jun 25 21:37:25 UTC 2007


------------------------------------------------------------
revno: 127
committer: James Westby <jw+debian at jameswestby.net>
branch nick: merge_upstream
timestamp: Mon 2007-06-25 22:37:25 +0100
message:
  Extend the import_dsc code to handle .dsc with no .orig.tar.gz.
  
  For the .dsc files with no .orig.tar.gz the upstream import must be looked up.
  The patch must be applied to the parent tree, but then use the last revision
  as a parent.
  
  Switch to calling out to patch and lsdiff to do the patching and give the
  information about what was touched.
modified:
  import_dsc.py
  tests/test_import_dsc.py
-------------- next part --------------
=== modified file 'import_dsc.py'
--- a/import_dsc.py	2007-06-24 21:21:25 +0000
+++ b/import_dsc.py	2007-06-25 21:37:25 +0000
@@ -19,21 +19,24 @@
 #
 
 import gzip
+import os
 from StringIO import StringIO
-import os
+from subprocess import Popen, PIPE
 
 import deb822
-from debian_bundle.debian_support import Version
+from debian_bundle.changelog import Version
 
-from bzrlib.bzrdir import BzrDir
-from bzrlib.errors import FileExists
-from bzrlib import generate_ids
+from bzrlib import (bzrdir,
+                    generate_ids,
+                    )
+from bzrlib.errors import FileExists, BzrError
 from bzrlib.transform import TreeTransform
 
 from bzrlib.plugins.bzrtools.upstream_import import (import_tar,
                                                      common_directory,
                                                      )
 
+from merge_upstream import make_upstream_tag
 import patches
 
 def _dsc_sorter(dscname1, dscname2):
@@ -52,90 +55,93 @@
   return v1 > v2
 
 
-def import_orig(tree, dsc):
-  for file_details in dsc['Files']:
-    origname = file_details['name']
-    if origname.endswith('.orig.tar.gz'):
-      f = open(origname, 'rb')
-      try:
-        import_tar(tree, f)
-        tree.commit('import upstream from %s' % (os.path.basename(origname)))
-      finally:
-        f.close()
-
-
-def import_diff(tree, dsc):
-  for file_details in dsc['Files']:
-    diffname = file_details['name']
-    if diffname.endswith('.diff.gz'):
-      f = gzip.GzipFile(diffname, 'rb')
-      try:
-        tt = TreeTransform(tree)
-        implied_parents = set()
-        def add_implied_parents(path):
-          parent = os.path.dirname(path)
-          if parent == '':
-            return
-          if parent in implied_parents:
-            return
-          implied_parents.add(parent)
-          add_implied_parents(parent)
-        patch_list = patches.parse_patches(f)
-        oldfiles = [patch.oldname for patch in patch_list]
-        newfiles = [patch.newname for patch in patch_list]
-        oldprefix = common_directory(oldfiles)
-        newprefix = common_directory(newfiles)
-        for patch in patch_list:
-          oldfilename = patch.oldname
-          newfilename = patch.newname
-          if oldprefix is not None:
-            oldfilename = oldfilename[len(oldprefix)+1:]
-            oldfilename = oldfilename.rstrip('/')
-          if oldfilename == '':
-            continue
-          if newprefix is not None:
-            newfilename = newfilename[len(newprefix)+1:]
-            newfilename = newfilename.rstrip('/')
-          if newfilename == '':
-            continue
-          oldid = tree.path2id(oldfilename)
-          if oldid is not None:
-            oldtext = StringIO(tree.get_file_text(oldid))
-          else:
-            oldtext = []
-          trans_id = tt.trans_id_tree_path(oldfilename)
-          newtext = list(patches.iter_patched(oldtext, StringIO(patch)))
-          if newtext == []:
-            tt.delete_versioned(trans_id)
-          else:
-            if oldid is not None:
-              tt.delete_contents(trans_id)
-            tt.create_file(newtext, trans_id)
-            if tt.tree_file_id(trans_id) is None:
-              name = os.path.basename(newfilename.rstrip('/'))
-              file_id = generate_ids.gen_file_id(name)
-              tt.version_file(file_id, trans_id)
-            add_implied_parents(newfilename)
-        for path in implied_parents:
-          trans_id = tt.trans_id_tree_path(path)
-          if tree.path2id(path) is None:
-            tt.create_directory(trans_id)
-          if tt.tree_file_id(trans_id) is None:
-            file_id = generate_ids.gen_file_id(name)
-            tt.version_file(file_id, trans_id)
-        tt.apply()
-        tree.commit('merge packaging changes from %s' % \
-                    (os.path.basename(diffname)))
-      finally:
-        f.close()
+def import_orig(tree, origname, version):
+  f = open(origname, 'rb')
+  try:
+    import_tar(tree, f)
+    tree.commit('import upstream from %s' % (os.path.basename(origname)))
+    upstream_version = version.upstream_version
+    tree.branch.tags.set_tag(make_upstream_tag(upstream_version),
+                             tree.branch.last_revision())
+  finally:
+    f.close()
+
+
+def import_diff(tree, diffname, version):
+  upstream_version = version.upstream_version
+  up_revid = tree.branch.tags.lookup_tag(make_upstream_tag(upstream_version))
+  up_tree = tree.branch.repository.revision_tree(up_revid)
+  current_revid = tree.branch.last_revision()
+  current_tree = tree.branch.repository.revision_tree(current_revid)
+  tree.revert([], tree.branch.repository.revision_tree(up_revid))
+  f = gzip.GzipFile(diffname, 'rb')
+  try:
+    cmd = ['patch', '--strip', '1', '--quiet', '--directory', tree.basedir]
+    child_proc = Popen(cmd, stdin=PIPE)
+    for line in f:
+      child_proc.stdin.write(line)
+    child_proc.stdin.close()
+    r = child_proc.wait()
+    if r != 0:
+      raise BzrError('patch failed')
+    f.seek(0)
+    cmd = ['lsdiff', '--strip', '1']
+    child_proc = Popen(cmd, stdin=PIPE, stdout=PIPE)
+    for line in f:
+      child_proc.stdin.write(line)
+    child_proc.stdin.close()
+    r = child_proc.wait()
+    if r != 0:
+      raise BzrError('patch failed')
+    touched_paths = []
+    for file in child_proc.stdout.readlines():
+      if file.endswith('\n'):
+        file = file[:-1]
+      touched_paths.append(file)
+    implied_parents = set()
+    def add_implied_parents(path, file_ids_from=None):
+      parent = os.path.dirname(path)
+      if parent == '':
+        return
+      if parent in implied_parents:
+        return
+      implied_parents.add(parent)
+      add_implied_parents(parent)
+      if file_ids_from is None:
+        tree.add([parent])
+      else:
+        file_id = file_ids_from.path2id(parent)
+        if file_id is None:
+          tree.add([parent])
+        else:
+          tree.add([parent], [file_id])
+    for path in touched_paths:
+      if not tree.has_filename(path):
+        tree.remove([path], verbose=False)
+      if not current_tree.has_filename(path):
+        add_implied_parents(path)
+        tree.add([path])
+      if not up_tree.has_filename(path) and current_tree.has_filename(path):
+        add_implied_parents(path, file_ids_from=current_tree)
+        file_id = current_tree.path2id(path)
+        if file_id is None:
+          tree.add([path])
+        else:
+          tree.add([path], [file_id])
+    tree.set_parent_ids([current_revid])
+    tree.commit('merge packaging changes from %s' % \
+                (os.path.basename(diffname)))
+  finally:
+    f.close()
 
 
 def import_dsc(target_dir, dsc_files):
-
   if os.path.exists(target_dir):
     raise FileExists(target_dir)
   os.mkdir(target_dir)
-  branch  = BzrDir.create_branch_convenience(target_dir)
+  format = bzrdir.format_registry.make_bzrdir('dirstate-tags')
+  branch  = bzrdir.BzrDir.create_branch_convenience(target_dir,
+                                                    format=format)
   tree = branch.bzrdir.open_workingtree()
   tree.lock_write()
   try:
@@ -146,8 +152,23 @@
         dsc = deb822.Dsc(f)
       finally:
         f.close()
-      import_orig(tree, dsc)
-      import_diff(tree, dsc)
+      orig_files = []
+      diff_files = []
+      for file_details in dsc['files']:
+        name = file_details['name']
+        if name.endswith('.orig.tar.gz'):
+          orig_files.append(name)
+        elif name.endswith('.diff.gz'):
+          diff_files.append(name)
+      assert len(orig_files) < 2, "I don't know how to import a source " \
+                                  "package with multiple .orig.tar.gz files."
+      assert len(diff_files) == 1, "I don't know how to import a source " \
+                                   "package which doesn't have a single " \
+                                   ".diff.gz file."
+      version = Version(dsc['Version'])
+      if len(orig_files) == 1:
+        import_orig(tree, orig_files[0], version)
+      import_diff(tree, diff_files[0], version)
   finally:
     tree.unlock()
 

=== modified file 'tests/test_import_dsc.py'
--- a/tests/test_import_dsc.py	2007-06-24 21:21:25 +0000
+++ b/tests/test_import_dsc.py	2007-06-25 21:37:25 +0000
@@ -35,13 +35,22 @@
   finally:
     f.close()
 
+def append_to_file(filename, contents):
+  f = open(filename, 'ab')
+  try:
+    f.write(contents)
+  finally:
+    f.close()
+
 class TestImportDsc(TestCaseWithTransport):
 
   basedir = 'package'
   target = 'target'
   orig_1 = 'package_0.1.orig.tar.gz'
   diff_1 = 'package_0.1-1.diff.gz'
+  diff_1b = 'package_0.1-2.diff.gz'
   dsc_1 = 'package_0.1-1.dsc'
+  dsc_1b = 'package_0.1-2.dsc'
 
   def make_base_package(self):
     os.mkdir(self.basedir)
@@ -63,17 +72,24 @@
     os.mkdir(os.path.join(diffdir, 'debian'))
     write_to_file(os.path.join(diffdir, 'debian', 'changelog'),
                   'version 1-1\n')
+    write_to_file(os.path.join(diffdir, 'debian', 'install'), 'install\n')
     write_to_file(os.path.join(diffdir, 'Makefile'), 'good command\n')
     os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
                                                    self.diff_1))
-    shutil.rmtree(diffdir)
-
-  def make_dsc_1(self):
-    self.make_orig_1()
-    self.make_diff_1()
-    write_to_file(self.dsc_1, """Format: 1.0
+
+  def make_diff_1b(self):
+    diffdir = 'package-0.1'
+    append_to_file(os.path.join(diffdir, 'debian', 'changelog'),
+                   'version 1-2\n')
+    write_to_file(os.path.join(diffdir, 'debian', 'control'), 'package\n')
+    os.unlink(os.path.join(diffdir, 'debian', 'install'))
+    os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
+                                                   self.diff_1b))
+
+  def make_dsc(self, filename, version, file1, file2=None):
+    write_to_file(filename, """Format: 1.0
 Source: package
-Version: 0.1-1
+Version: %s
 Binary: package
 Maintainer: maintainer <maint at maint.org>
 Architecture: any
@@ -81,13 +97,29 @@
 Build-Depends: debhelper (>= 5.0.0)
 Files:
  8636a3e8ae81664bac70158503aaf53a 1328218 %s
-  1acd97ad70445afd5f2a64858296f21c 20709 %s
-""" % (self.orig_1, self.diff_1))
+""" % (version, file1))
+    if file2 is not None:
+      append_to_file(filename,
+                     " 1acd97ad70445afd5f2a64858296f21c 20709 %s" % file2)
+
+  def make_dsc_1(self):
+    self.make_orig_1()
+    self.make_diff_1()
+    self.make_dsc(self.dsc_1, '0.1-1', self.orig_1, self.diff_1)
+
+  def make_dsc_1b(self):
+    self.make_diff_1b()
+    self.make_dsc(self.dsc_1b, '0.1-2', self.diff_1b)
 
   def import_dsc_1(self):
     self.make_dsc_1()
     import_dsc(self.target, [self.dsc_1])
 
+  def import_dsc_1b(self):
+    self.make_dsc_1()
+    self.make_dsc_1b()
+    import_dsc(self.target, [self.dsc_1, self.dsc_1b])
+
   def test_import_dsc_target_extant(self):
     os.mkdir(self.target)
     write_to_file('package_0.1.dsc', '')
@@ -99,7 +131,7 @@
     tree = WorkingTree.open_containing(self.target)[0]
     tree.lock_read()
     expected_inv = ['README', 'CHANGELOG', 'Makefile', 'debian/',
-                    'debian/changelog']
+                    'debian/changelog', 'debian/install']
     try:
       self.check_inventory_shape(tree.inventory, expected_inv)
     finally:
@@ -132,11 +164,13 @@
     self.assertEqual(msg, 'merge packaging changes from %s' % self.diff_1)
     changes = tree.changes_from(tree.branch.repository.revision_tree(rh[0]))
     added = changes.added
-    self.assertEqual(len(added), 2)
+    self.assertEqual(len(added), 3)
     self.assertEqual(added[0][0], 'debian')
     self.assertEqual(added[0][2], 'directory')
     self.assertEqual(added[1][0], 'debian/changelog')
     self.assertEqual(added[1][2], 'file')
+    self.assertEqual(added[2][0], 'debian/install')
+    self.assertEqual(added[2][2], 'file')
     self.assertEqual(len(changes.removed), 0)
     self.assertEqual(len(changes.renamed), 0)
     modified = changes.modified
@@ -145,4 +179,61 @@
     self.assertEqual(modified[0][2], 'file')
     self.assertEqual(modified[0][3], True)
     self.assertEqual(modified[0][4], False)
+    tag = tree.branch.tags.lookup_tag('upstream-0.1')
+    self.assertEqual(tag, rh[0])
+
+  def test_import_two_dsc_one_upstream_tree(self):
+    self.import_dsc_1b()
+    self.failUnlessExists(self.target)
+    tree = WorkingTree.open_containing(self.target)[0]
+    tree.lock_read()
+    expected_inv = ['README', 'CHANGELOG', 'Makefile', 'debian/',
+                    'debian/changelog', 'debian/control']
+    try:
+      self.check_inventory_shape(tree.inventory, expected_inv)
+    finally:
+      tree.unlock()
+    for path in expected_inv:
+      self.failUnlessExists(os.path.join(self.target, path))
+    f = open(os.path.join(self.target, 'Makefile'))
+    try:
+      contents = f.read()
+    finally:
+      f.close()
+    self.assertEqual(contents, 'good command\n')
+    f = open(os.path.join(self.target, 'debian', 'changelog'))
+    try:
+      contents = f.read()
+    finally:
+      f.close()
+    self.assertEqual(contents, 'version 1-1\nversion 1-2\n')
+    self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(),
+                     False)
+
+  def test_import_two_dsc_one_upstream_history(self):
+    self.import_dsc_1b()
+    tree = WorkingTree.open_containing(self.target)[0]
+    rh = tree.branch.revision_history()
+    self.assertEqual(len(rh), 3)
+    msg = tree.branch.repository.get_revision(rh[0]).message
+    self.assertEqual(msg, 'import upstream from %s' % self.orig_1)
+    msg = tree.branch.repository.get_revision(rh[1]).message
+    self.assertEqual(msg, 'merge packaging changes from %s' % self.diff_1)
+    msg = tree.branch.repository.get_revision(rh[2]).message
+    self.assertEqual(msg, 'merge packaging changes from %s' % self.diff_1b)
+    changes = tree.changes_from(tree.branch.repository.revision_tree(rh[1]))
+    added = changes.added
+    self.assertEqual(len(added), 1, str(added))
+    self.assertEqual(added[0][0], 'debian/control')
+    self.assertEqual(added[0][2], 'file')
+    self.assertEqual(len(changes.removed), 1)
+    self.assertEqual(changes.removed[0][0], 'debian/install')
+    self.assertEqual(changes.removed[0][2], 'file')
+    self.assertEqual(len(changes.renamed), 0)
+    modified = changes.modified
+    self.assertEqual(len(modified), 1)
+    self.assertEqual(modified[0][0], 'debian/changelog')
+    self.assertEqual(modified[0][2], 'file')
+    self.assertEqual(modified[0][3], True)
+    self.assertEqual(modified[0][4], False)
 



More information about the Pkg-bazaar-commits mailing list