[Pkg-bazaar-commits] r136 ./bzr-builddeb/people/jdw/merge_upstream: Add tests for non-native -> native transition on import.
James Westby
jw+debian at jameswestby.net
Sun Jul 1 14:13:48 UTC 2007
------------------------------------------------------------
revno: 136
committer: James Westby <jw+debian at jameswestby.net>
branch nick: merge_upstream
timestamp: Sun 2007-07-01 15:13:48 +0100
message:
Add tests for non-native -> native transition on import.
When transitioning from a non-native package to native the first native version
is a merge of the last upstream and the last packaging changes. This required
pulling the import_tar code out of bzrtools, so that when a file moves from
the packaging branch to the native branch the file id is maintained.
I am not convinced that all cases are handled here, but it is a start.
modified:
import_dsc.py
tests/test_import_dsc.py
-------------- next part --------------
=== modified file 'import_dsc.py'
--- a/import_dsc.py 2007-06-30 21:03:01 +0000
+++ b/import_dsc.py 2007-07-01 14:13:48 +0000
@@ -21,18 +21,24 @@
import gzip
import os
from subprocess import Popen, PIPE
+import tarfile
import deb822
from debian_bundle.changelog import Version
from bzrlib import (bzrdir,
+ generate_ids,
urlutils,
)
from bzrlib.errors import FileExists, BzrError
+from bzrlib.osutils import file_iterator, isdir, basename
from bzrlib.trace import warning, info
+from bzrlib.transform import TreeTransform, cook_conflicts, resolve_conflicts
from bzrlib.transport import get_transport
-from bzrlib.plugins.bzrtools.upstream_import import (import_tar,
+from bzrlib.plugins.bzrtools.upstream_import import (common_directory,
+ names_of_files,
+ add_implied_parents,
)
from errors import ImportError
@@ -41,6 +47,101 @@
# TODO: Allow native->non-native transitions and back
# TODO: support explicit upstream branch.
+def import_tar(tree, tar_input, file_ids_from=None):
+ """Replace the contents of a working directory with tarfile contents.
+ The tarfile may be a gzipped stream. File ids will be updated.
+ """
+ tar_file = tarfile.open('lala', 'r', tar_input)
+ import_archive(tree, tar_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)
+ else:
+ tt.create_directory(trans_id)
+
+
+def import_archive(tree, archive_file, file_ids_from=None):
+ prefix = common_directory(names_of_files(archive_file))
+ tt = TreeTransform(tree)
+
+ removed = set()
+ for path, entry in tree.inventory.iter_entries():
+ if entry.parent_id is None:
+ continue
+ trans_id = tt.trans_id_tree_path(path)
+ tt.delete_contents(trans_id)
+ removed.add(path)
+
+ added = set()
+ implied_parents = set()
+ seen = set()
+ for member in archive_file.getmembers():
+ if member.type == 'g':
+ # type 'g' is a header
+ continue
+ relative_path = member.name
+ if prefix is not None:
+ relative_path = relative_path[len(prefix)+1:]
+ relative_path = relative_path.rstrip('/')
+ if relative_path == '':
+ continue
+ add_implied_parents(implied_parents, relative_path)
+ trans_id = tt.trans_id_tree_path(relative_path)
+ added.add(relative_path.rstrip('/'))
+ path = tree.abspath(relative_path)
+ if member.name in seen:
+ if tt.final_kind(trans_id) == 'file':
+ tt.set_executability(None, trans_id)
+ tt.cancel_creation(trans_id)
+ seen.add(member.name)
+ if member.isreg():
+ tt.create_file(file_iterator(archive_file.extractfile(member)),
+ trans_id)
+ executable = (member.mode & 0111) != 0
+ tt.set_executability(executable, trans_id)
+ elif member.isdir():
+ do_directory(tt, trans_id, tree, relative_path, path)
+ elif member.issym():
+ tt.create_symlink(member.linkname, trans_id)
+ else:
+ continue
+ 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:
+ name = basename(member.name.rstrip('/'))
+ file_id = generate_ids.gen_file_id(name)
+ tt.version_file(file_id, trans_id)
+
+ for relative_path in implied_parents.difference(added):
+ if relative_path == "":
+ continue
+ trans_id = tt.trans_id_tree_path(relative_path)
+ 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:
+ tt.version_file(trans_id, trans_id)
+ added.add(relative_path)
+
+ for path in removed.difference(added):
+ tt.unversion_file(tt.trans_id_tree_path(path))
+
+ for conflict in cook_conflicts(resolve_conflicts(tt), tt):
+ warning(conflict)
+ tt.apply()
+
+
def open_file(path, transport, base_dir=None):
"""Open a file, possibly over a transport.
@@ -108,13 +209,15 @@
f = open_file(origname, transport, base_dir=base_dir)[0]
try:
dangling_revid = None
+ dangling_tree = None
if last_upstream is not None:
dangling_revid = tree.branch.last_revision()
+ dangling_tree = tree.branch.repository.revision_tree(dangling_revid)
old_upstream_revid = tree.branch.tags.lookup_tag(
make_upstream_tag(last_upstream))
tree.revert([],
tree.branch.repository.revision_tree(old_upstream_revid))
- import_tar(tree, f)
+ 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)
@@ -127,16 +230,21 @@
f.close()
return dangling_revid
- def import_native(self, tree, origname, version, dangling_revid=None,
- last_upstream=None, transport=None, base_dir=None):
+ def import_native(self, tree, origname, version, last_upstream=None,
+ transport=None, base_dir=None):
f = open_file(origname, transport, base_dir=base_dir)[0]
try:
+ dangling_revid = None
+ dangling_tree = None
if last_upstream is not None:
old_upstream_revid = tree.branch.tags.lookup_tag(
make_upstream_tag(last_upstream))
+ if old_upstream_revid != tree.branch.last_revision():
+ dangling_revid = tree.branch.last_revision()
+ dangling_tree = tree.branch.repository.revision_tree(dangling_revid)
tree.revert([],
tree.branch.repository.revision_tree(old_upstream_revid))
- import_tar(tree, f)
+ 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)
@@ -176,6 +284,44 @@
touched_paths.append(filename)
return touched_paths
+ def _add_implied_parents(self, tree, 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)
+ self._add_implied_parents(tree, implied_parents, parent,
+ file_ids_from=file_ids_from)
+ 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])
+
+ def _update_path_info(self, tree, touched_paths, other_parent, main_parent):
+ implied_parents = set()
+ for path in touched_paths:
+ if not tree.has_filename(path):
+ tree.remove([path], verbose=False)
+ elif not other_parent.has_filename(path):
+ self._add_implied_parents(tree, implied_parents, path,
+ file_ids_from=other_parent)
+ tree.add([path])
+ elif not (main_parent.has_filename(path) and
+ other_parent.has_filename(path)):
+ self._add_implied_parents(tree, implied_parents, path,
+ file_ids_from=other_parent)
+ file_id = other_parent.path2id(path)
+ if file_id is None:
+ tree.add([path])
+ else:
+ tree.add([path], [file_id])
+
def import_diff(self, tree, diffname, version, dangling_revid=None,
transport=None, base_dir=None):
upstream_version = version.upstream_version
@@ -193,38 +339,7 @@
self._patch_tree(f, tree.basedir)
f.seek(0)
touched_paths = self._get_touched_paths(f)
- 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])
+ self._update_path_info(tree, touched_paths, current_tree, up_tree)
if dangling_revid is not None:
tree.add_parent_tree_id(dangling_revid)
tree.commit('merge packaging changes from %s' % \
@@ -335,10 +450,8 @@
dangling_revid = None
elif type == 'native':
self.import_native(tree, filename, version,
- dangling_revid=dangling_revid,
last_upstream=last_upstream,
transport=transport, base_dir=base_dir)
- dangling_revid = None
last_upstream = version.upstream_version
info("imported %s" % filename)
finally:
=== modified file 'tests/test_import_dsc.py'
--- a/tests/test_import_dsc.py 2007-06-30 21:03:01 +0000
+++ b/tests/test_import_dsc.py 2007-07-01 14:13:48 +0000
@@ -71,6 +71,7 @@
def extend_base_package(self):
write_to_file(os.path.join(self.basedir, 'NEWS'), 'new release\n')
write_to_file(os.path.join(self.basedir, 'Makefile'), 'good command\n')
+ write_to_file(os.path.join(self.basedir, 'from_debian'), 'from debian\n')
def make_orig_1(self):
self.make_base_package()
@@ -113,6 +114,7 @@
append_to_file(os.path.join(diffdir, 'debian', 'changelog'),
'version 1-3\n')
write_to_file(os.path.join(diffdir, 'debian', 'install'), 'install\n')
+ write_to_file(os.path.join(diffdir, 'from_debian'), 'from debian\n')
os.system('diff -Nru %s %s | gzip -9 - > %s' % (self.basedir, diffdir,
self.diff_1c))
@@ -354,8 +356,9 @@
self.failUnlessExists(self.target)
tree = WorkingTree.open(self.target)
tree.lock_read()
- expected_inv = ['README', 'CHANGELOG', 'Makefile', 'debian/',
- 'debian/changelog', 'debian/control', 'debian/install']
+ expected_inv = ['README', 'CHANGELOG', 'Makefile', 'from_debian',
+ 'debian/', 'debian/changelog', 'debian/control',
+ 'debian/install']
try:
self.check_inventory_shape(tree.inventory, expected_inv)
finally:
@@ -392,9 +395,10 @@
self.assertEqual(msg, 'merge packaging changes from %s' % self.diff_1c)
changes = tree.changes_from(tree.branch.repository.revision_tree(rh[2]))
added = changes.added
- self.assertEqual(len(added), 1, str(added))
+ self.assertEqual(len(added), 2, str(added))
self.assertEqual(added[0][0], 'debian/install')
self.assertEqual(added[0][2], 'file')
+ self.assertEqual(added[1][0], 'from_debian')
self.assertEqual(len(changes.removed), 0)
self.assertEqual(len(changes.renamed), 0)
modified = changes.modified
@@ -409,8 +413,8 @@
self.failUnlessExists(self.target)
tree = WorkingTree.open(self.target)
tree.lock_read()
- expected_inv = ['README', 'CHANGELOG', 'Makefile', 'NEWS', 'debian/',
- 'debian/changelog', 'debian/install']
+ expected_inv = ['README', 'CHANGELOG', 'Makefile', 'NEWS', 'from_debian',
+ 'debian/', 'debian/changelog', 'debian/install']
try:
self.check_inventory_shape(tree.inventory, expected_inv)
finally:
@@ -466,7 +470,7 @@
# Check the diff against last packaging version
changes = tree.changes_from(
tree.branch.repository.revision_tree(parents[1]))
- self.assertEqual(len(changes.added), 1)
+ self.assertEqual(len(changes.added), 1, str(changes.added))
self.assertEqual(changes.added[0][0], 'NEWS')
self.assertEqual(changes.added[0][2], 'file')
self.assertEqual(len(changes.removed), 1)
@@ -587,6 +591,18 @@
tar.close()
self.make_dsc(self.native_dsc_2, '0.2', self.native_2)
+ def make_native_dsc_2_after_non_native(self):
+ self.extend_base_package()
+ os.mkdir(os.path.join(self.basedir, 'debian'))
+ write_to_file(os.path.join(self.basedir, 'debian', 'changelog'),
+ 'version 1\nversion 2\n')
+ tar = tarfile.open(self.native_2, 'w:gz')
+ try:
+ tar.add(self.basedir)
+ finally:
+ tar.close()
+ self.make_dsc(self.native_dsc_2, '0.2', self.native_2)
+
def test_import_dsc_native_single(self):
self.make_native_dsc_1()
importer = DscImporter([self.native_dsc_1])
@@ -613,8 +629,8 @@
importer = DscImporter([self.native_dsc_1, self.native_dsc_2])
importer.import_dsc(self.target)
tree = WorkingTree.open(self.target)
- expected_inv = ['CHANGELOG', 'README', 'Makefile', 'NEWS', 'debian/',
- 'debian/changelog']
+ expected_inv = ['CHANGELOG', 'README', 'Makefile', 'NEWS', 'from_debian',
+ 'debian/', 'debian/changelog']
tree.lock_read()
try:
self.check_inventory_shape(tree.inventory, expected_inv)
@@ -634,3 +650,53 @@
parents = tree.branch.repository.revision_tree(rh[1]).get_parent_ids()
self.assertEqual(len(parents), 1)
+ def test_non_native_to_native(self):
+ self.make_dsc_1()
+ self.make_native_dsc_2_after_non_native()
+ importer = DscImporter([self.dsc_1, self.native_dsc_2])
+ importer.import_dsc(self.target)
+ tree = WorkingTree.open(self.target)
+ expected_inv = ['CHANGELOG', 'README', 'Makefile', 'NEWS', 'from_debian',
+ 'debian/', 'debian/changelog']
+ tree.lock_read()
+ try:
+ self.check_inventory_shape(tree.inventory, expected_inv)
+ finally:
+ tree.unlock()
+ self.assertEqual(tree.changes_from(tree.basis_tree()).has_changed(), False)
+ rh = tree.branch.revision_history()
+ self.assertEqual(len(rh), 2)
+ rev = tree.branch.repository.get_revision(rh[0])
+ self.assertEqual(rev.message,
+ "import upstream from %s" % \
+ os.path.basename(self.orig_1))
+ rev = tree.branch.repository.get_revision(rh[1])
+ self.assertEqual(rev.message,
+ "import package from %s" % \
+ os.path.basename(self.native_2))
+ self.assertEqual(len(tree.get_parent_ids()), 1)
+ parents = tree.branch.repository.revision_tree(rh[1]).get_parent_ids()
+ self.assertEqual(len(parents), 2)
+ rev = tree.branch.repository.get_revision(parents[1])
+ self.assertEqual(rev.message,
+ "merge packaging changes from %s" % \
+ os.path.basename(self.diff_1))
+ changes = tree.changes_from(tree.branch.repository.revision_tree(rh[0]))
+ self.assertEqual(len(changes.added), 4)
+ self.assertEqual(changes.added[0][0], 'NEWS')
+ self.assertEqual(changes.added[1][0], 'debian')
+ self.assertEqual(changes.added[2][0], 'debian/changelog')
+ self.assertEqual(changes.added[3][0], 'from_debian')
+ self.assertEqual(len(changes.modified), 1)
+ self.assertEqual(changes.modified[0][0], 'Makefile')
+ self.assertEqual(changes.removed, [])
+ changes = tree.changes_from(
+ tree.branch.repository.revision_tree(parents[1]))
+ self.assertEqual(len(changes.added), 2)
+ self.assertEqual(changes.added[0][0], 'NEWS')
+ self.assertEqual(changes.added[1][0], 'from_debian')
+ self.assertEqual(len(changes.modified), 1, str(changes.modified))
+ self.assertEqual(changes.modified[0][0], 'debian/changelog')
+ self.assertEqual(len(changes.removed), 1)
+ self.assertEqual(changes.removed[0][0], 'debian/install')
+
More information about the Pkg-bazaar-commits
mailing list