/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Marius Kruger
  • Date: 2010-07-10 21:28:56 UTC
  • mto: (5384.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5385.
  • Revision ID: marius.kruger@enerweb.co.za-20100710212856-uq4ji3go0u5se7hx
* Update documentation
* add NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2012, 2016 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
 
from .. import (
 
18
from bzrlib import (
 
19
    chk_map,
 
20
    groupcompress,
 
21
    bzrdir,
19
22
    errors,
 
23
    inventory,
20
24
    osutils,
21
25
    repository,
22
26
    revision,
23
27
    tests,
24
 
    workingtree,
25
 
    )
26
 
from ..sixish import text_type
27
 
from ..bzr import (
28
 
    chk_map,
29
 
    groupcompress,
30
 
    inventory,
31
 
    )
32
 
from ..bzr.inventory import (
33
 
    CHKInventory,
34
 
    Inventory,
35
 
    ROOT_ID,
36
 
    InventoryFile,
37
 
    InventoryDirectory,
38
 
    InventoryEntry,
39
 
    TreeReference,
40
 
    mutable_inventory_from_tree,
41
 
    )
42
 
from . import (
 
28
    )
 
29
from bzrlib.inventory import (CHKInventory, Inventory, ROOT_ID, InventoryFile,
 
30
    InventoryDirectory, InventoryEntry, TreeReference)
 
31
from bzrlib.tests import (
43
32
    TestCase,
44
33
    TestCaseWithTransport,
 
34
    condition_isinstance,
 
35
    multiply_tests,
 
36
    split_suite_by_condition,
45
37
    )
46
 
from .scenarios import load_tests_apply_scenarios
47
 
 
48
 
 
49
 
load_tests = load_tests_apply_scenarios
50
 
 
51
 
 
52
 
def delta_application_scenarios():
 
38
from bzrlib.tests.per_workingtree import workingtree_formats
 
39
 
 
40
 
 
41
def load_tests(standard_tests, module, loader):
 
42
    """Parameterise some inventory tests."""
 
43
    to_adapt, result = split_suite_by_condition(standard_tests,
 
44
        condition_isinstance(TestDeltaApplication))
53
45
    scenarios = [
54
 
        ('Inventory', {'apply_delta': apply_inventory_Inventory}),
 
46
        ('Inventory', {'apply_delta':apply_inventory_Inventory}),
55
47
        ]
56
48
    # Working tree basis delta application
57
49
    # Repository add_inv_by_delta.
60
52
    # just creating trees.
61
53
    formats = set()
62
54
    for _, format in repository.format_registry.iteritems():
63
 
        if format.supports_full_versioned_files:
64
 
            scenarios.append((str(format.__name__), {
65
 
                'apply_delta': apply_inventory_Repository_add_inventory_by_delta,
66
 
                'format': format}))
67
 
    for getter in workingtree.format_registry._get_all_lazy():
68
 
        try:
69
 
            format = getter()
70
 
            if callable(format):
71
 
                format = format()
72
 
        except ImportError:
73
 
            pass  # Format with unmet dependency
74
 
        repo_fmt = format._matchingcontroldir.repository_format
75
 
        if not repo_fmt.supports_full_versioned_files:
76
 
            continue
 
55
        scenarios.append((str(format.__name__), {
 
56
            'apply_delta':apply_inventory_Repository_add_inventory_by_delta,
 
57
            'format':format}))
 
58
    for format in workingtree_formats():
77
59
        scenarios.append(
78
60
            (str(format.__class__.__name__) + ".update_basis_by_delta", {
79
 
                'apply_delta': apply_inventory_WT_basis,
80
 
                'format': format}))
 
61
            'apply_delta':apply_inventory_WT_basis,
 
62
            'format':format}))
81
63
        scenarios.append(
82
64
            (str(format.__class__.__name__) + ".apply_inventory_delta", {
83
 
                'apply_delta': apply_inventory_WT,
84
 
                'format': format}))
85
 
    return scenarios
 
65
            'apply_delta':apply_inventory_WT,
 
66
            'format':format}))
 
67
    return multiply_tests(to_adapt, scenarios, result)
86
68
 
87
69
 
88
70
def create_texts_for_inv(repo, inv):
89
71
    for path, ie in inv.iter_entries():
90
72
        if ie.text_size:
91
 
            lines = [b'a' * ie.text_size]
 
73
            lines = ['a' * ie.text_size]
92
74
        else:
93
75
            lines = []
94
76
        repo.texts.add_lines((ie.file_id, ie.revision), [], lines)
95
 
 
96
 
 
97
 
def apply_inventory_Inventory(self, basis, delta, invalid_delta=True):
 
77
    
 
78
def apply_inventory_Inventory(self, basis, delta):
98
79
    """Apply delta to basis and return the result.
99
 
 
 
80
    
100
81
    :param basis: An inventory to be used as the basis.
101
82
    :param delta: The inventory delta to apply:
102
83
    :return: An inventory resulting from the application.
105
86
    return basis
106
87
 
107
88
 
108
 
def apply_inventory_WT(self, basis, delta, invalid_delta=True):
 
89
def apply_inventory_WT(self, basis, delta):
109
90
    """Apply delta to basis and return the result.
110
91
 
111
92
    This sets the tree state to be basis, and then calls apply_inventory_delta.
112
 
 
 
93
    
113
94
    :param basis: An inventory to be used as the basis.
114
95
    :param delta: The inventory delta to apply:
115
96
    :return: An inventory resulting from the application.
116
97
    """
117
 
    control = self.make_controldir(
118
 
        'tree', format=self.format._matchingcontroldir)
 
98
    control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
119
99
    control.create_repository()
120
100
    control.create_branch()
121
101
    tree = self.format.initialize(control)
125
105
    finally:
126
106
        tree.unlock()
127
107
    # Fresh object, reads disk again.
128
 
    tree = tree.controldir.open_workingtree()
 
108
    tree = tree.bzrdir.open_workingtree()
129
109
    tree.lock_write()
130
110
    try:
131
111
        tree.apply_inventory_delta(delta)
132
112
    finally:
133
113
        tree.unlock()
134
114
    # reload tree - ensure we get what was written.
135
 
    tree = tree.controldir.open_workingtree()
 
115
    tree = tree.bzrdir.open_workingtree()
136
116
    tree.lock_read()
137
117
    self.addCleanup(tree.unlock)
138
 
    if not invalid_delta:
139
 
        tree._validate()
140
 
    return tree.root_inventory
141
 
 
142
 
 
143
 
def _create_repo_revisions(repo, basis, delta, invalid_delta):
144
 
    with repository.WriteGroup(repo):
145
 
        rev = revision.Revision(b'basis', timestamp=0, timezone=None,
146
 
                                message="", committer="foo@example.com")
147
 
        basis.revision_id = b'basis'
148
 
        create_texts_for_inv(repo, basis)
149
 
        repo.add_revision(b'basis', rev, basis)
150
 
        if invalid_delta:
151
 
            # We don't want to apply the delta to the basis, because we expect
152
 
            # the delta is invalid.
153
 
            result_inv = basis
154
 
            result_inv.revision_id = b'result'
155
 
            target_entries = None
156
 
        else:
157
 
            result_inv = basis.create_by_apply_delta(delta, b'result')
158
 
            create_texts_for_inv(repo, result_inv)
159
 
            target_entries = list(result_inv.iter_entries_by_dir())
160
 
        rev = revision.Revision(b'result', timestamp=0, timezone=None,
161
 
                                message="", committer="foo@example.com")
162
 
        repo.add_revision(b'result', rev, result_inv)
163
 
    return target_entries
164
 
 
165
 
 
166
 
def _get_basis_entries(tree):
167
 
    basis_tree = tree.basis_tree()
168
 
    with basis_tree.lock_read():
169
 
        return list(basis_tree.inventory.iter_entries_by_dir())
170
 
 
171
 
 
172
 
def _populate_different_tree(tree, basis, delta):
173
 
    """Put all entries into tree, but at a unique location."""
174
 
    added_ids = set()
175
 
    added_paths = set()
176
 
    tree.add(['unique-dir'], [b'unique-dir-id'], ['directory'])
177
 
    for path, ie in basis.iter_entries_by_dir():
178
 
        if ie.file_id in added_ids:
179
 
            continue
180
 
        # We want a unique path for each of these, we use the file-id
181
 
        tree.add(['unique-dir/' + ie.file_id], [ie.file_id], [ie.kind])
182
 
        added_ids.add(ie.file_id)
183
 
    for old_path, new_path, file_id, ie in delta:
184
 
        if file_id in added_ids:
185
 
            continue
186
 
        tree.add(['unique-dir/' + file_id], [file_id], [ie.kind])
187
 
 
188
 
 
189
 
def apply_inventory_WT_basis(test, basis, delta, invalid_delta=True):
 
118
    # One could add 'tree._validate' here but that would cause 'early' failues 
 
119
    # as far as higher level code is concerned. Possibly adding an
 
120
    # expect_fail parameter to this function and if that is False then do a
 
121
    # validate call.
 
122
    return tree.inventory
 
123
 
 
124
 
 
125
def apply_inventory_WT_basis(self, basis, delta):
190
126
    """Apply delta to basis and return the result.
191
127
 
192
128
    This sets the parent and then calls update_basis_by_delta.
194
130
    allow safety checks made by the WT to succeed, and finally ensures that all
195
131
    items in the delta with a new path are present in the WT before calling
196
132
    update_basis_by_delta.
197
 
 
 
133
    
198
134
    :param basis: An inventory to be used as the basis.
199
135
    :param delta: The inventory delta to apply:
200
136
    :return: An inventory resulting from the application.
201
137
    """
202
 
    control = test.make_controldir(
203
 
        'tree', format=test.format._matchingcontroldir)
 
138
    control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
204
139
    control.create_repository()
205
140
    control.create_branch()
206
 
    tree = test.format.initialize(control)
 
141
    tree = self.format.initialize(control)
207
142
    tree.lock_write()
208
143
    try:
209
 
        target_entries = _create_repo_revisions(tree.branch.repository, basis,
210
 
                                                delta, invalid_delta)
 
144
        repo = tree.branch.repository
 
145
        repo.start_write_group()
 
146
        try:
 
147
            rev = revision.Revision('basis', timestamp=0, timezone=None,
 
148
                message="", committer="foo@example.com")
 
149
            basis.revision_id = 'basis'
 
150
            create_texts_for_inv(tree.branch.repository, basis)
 
151
            repo.add_revision('basis', rev, basis)
 
152
            # Add a revision for the result, with the basis content - 
 
153
            # update_basis_by_delta doesn't check that the delta results in
 
154
            # result, and we want inconsistent deltas to get called on the
 
155
            # tree, or else the code isn't actually checked.
 
156
            rev = revision.Revision('result', timestamp=0, timezone=None,
 
157
                message="", committer="foo@example.com")
 
158
            basis.revision_id = 'result'
 
159
            repo.add_revision('result', rev, basis)
 
160
            repo.commit_write_group()
 
161
        except:
 
162
            repo.abort_write_group()
 
163
            raise
211
164
        # Set the basis state as the trees current state
212
165
        tree._write_inventory(basis)
213
166
        # This reads basis from the repo and puts it into the tree's local
214
167
        # cache, if it has one.
215
 
        tree.set_parent_ids([b'basis'])
 
168
        tree.set_parent_ids(['basis'])
 
169
        paths = {}
 
170
        parents = set()
 
171
        for old, new, id, entry in delta:
 
172
            if None in (new, entry):
 
173
                continue
 
174
            paths[new] = (entry.file_id, entry.kind)
 
175
            parents.add(osutils.dirname(new))
 
176
        parents = osutils.minimum_path_selection(parents)
 
177
        parents.discard('')
 
178
        # Put place holders in the tree to permit adding the other entries.
 
179
        for pos, parent in enumerate(parents):
 
180
            if not tree.path2id(parent):
 
181
                # add a synthetic directory in the tree so we can can put the
 
182
                # tree0 entries in place for dirstate.
 
183
                tree.add([parent], ["id%d" % pos], ["directory"])
 
184
        if paths:
 
185
            # Many deltas may cause this mini-apply to fail, but we want to see what
 
186
            # the delta application code says, not the prep that we do to deal with 
 
187
            # limitations of dirstate's update_basis code.
 
188
            for path, (file_id, kind) in sorted(paths.items()):
 
189
                try:
 
190
                    tree.add([path], [file_id], [kind])
 
191
                except (KeyboardInterrupt, SystemExit):
 
192
                    raise
 
193
                except:
 
194
                    pass
216
195
    finally:
217
196
        tree.unlock()
218
197
    # Fresh lock, reads disk again.
219
 
    with tree.lock_write():
220
 
        tree.update_basis_by_delta(b'result', delta)
221
 
        if not invalid_delta:
222
 
            tree._validate()
 
198
    tree.lock_write()
 
199
    try:
 
200
        tree.update_basis_by_delta('result', delta)
 
201
    finally:
 
202
        tree.unlock()
223
203
    # reload tree - ensure we get what was written.
224
 
    tree = tree.controldir.open_workingtree()
 
204
    tree = tree.bzrdir.open_workingtree()
225
205
    basis_tree = tree.basis_tree()
226
206
    basis_tree.lock_read()
227
 
    test.addCleanup(basis_tree.unlock)
228
 
    basis_inv = basis_tree.root_inventory
229
 
    if target_entries:
230
 
        basis_entries = list(basis_inv.iter_entries_by_dir())
231
 
        test.assertEqual(target_entries, basis_entries)
232
 
    return basis_inv
233
 
 
234
 
 
235
 
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta,
236
 
                                                      invalid_delta=True):
 
207
    self.addCleanup(basis_tree.unlock)
 
208
    # Note, that if the tree does not have a local cache, the trick above of
 
209
    # setting the result as the basis, will come back to bite us. That said,
 
210
    # all the implementations in bzr do have a local cache.
 
211
    return basis_tree.inventory
 
212
 
 
213
 
 
214
def apply_inventory_Repository_add_inventory_by_delta(self, basis, delta):
237
215
    """Apply delta to basis and return the result.
238
 
 
 
216
    
239
217
    This inserts basis as a whole inventory and then uses
240
218
    add_inventory_by_delta to add delta.
241
219
 
244
222
    :return: An inventory resulting from the application.
245
223
    """
246
224
    format = self.format()
247
 
    control = self.make_controldir('tree', format=format._matchingcontroldir)
 
225
    control = self.make_bzrdir('tree', format=format._matchingbzrdir)
248
226
    repo = format.initialize(control)
249
 
    with repo.lock_write(), repository.WriteGroup(repo):
250
 
        rev = revision.Revision(
251
 
            b'basis', timestamp=0, timezone=None, message="",
252
 
            committer="foo@example.com")
253
 
        basis.revision_id = b'basis'
254
 
        create_texts_for_inv(repo, basis)
255
 
        repo.add_revision(b'basis', rev, basis)
256
 
    with repo.lock_write(), repository.WriteGroup(repo):
257
 
        inv_sha1 = repo.add_inventory_by_delta(
258
 
            b'basis', delta, b'result', [b'basis'])
 
227
    repo.lock_write()
 
228
    try:
 
229
        repo.start_write_group()
 
230
        try:
 
231
            rev = revision.Revision('basis', timestamp=0, timezone=None,
 
232
                message="", committer="foo@example.com")
 
233
            basis.revision_id = 'basis'
 
234
            create_texts_for_inv(repo, basis)
 
235
            repo.add_revision('basis', rev, basis)
 
236
            repo.commit_write_group()
 
237
        except:
 
238
            repo.abort_write_group()
 
239
            raise
 
240
    finally:
 
241
        repo.unlock()
 
242
    repo.lock_write()
 
243
    try:
 
244
        repo.start_write_group()
 
245
        try:
 
246
            inv_sha1 = repo.add_inventory_by_delta('basis', delta,
 
247
                'result', ['basis'])
 
248
        except:
 
249
            repo.abort_write_group()
 
250
            raise
 
251
        else:
 
252
            repo.commit_write_group()
 
253
    finally:
 
254
        repo.unlock()
259
255
    # Fresh lock, reads disk again.
260
 
    repo = repo.controldir.open_repository()
 
256
    repo = repo.bzrdir.open_repository()
261
257
    repo.lock_read()
262
258
    self.addCleanup(repo.unlock)
263
 
    return repo.get_inventory(b'result')
 
259
    return repo.get_inventory('result')
264
260
 
265
261
 
266
262
class TestInventoryUpdates(TestCase):
267
263
 
268
264
    def test_creation_from_root_id(self):
269
265
        # iff a root id is passed to the constructor, a root directory is made
270
 
        inv = inventory.Inventory(root_id=b'tree-root')
 
266
        inv = inventory.Inventory(root_id='tree-root')
271
267
        self.assertNotEqual(None, inv.root)
272
 
        self.assertEqual(b'tree-root', inv.root.file_id)
 
268
        self.assertEqual('tree-root', inv.root.file_id)
273
269
 
274
270
    def test_add_path_of_root(self):
275
271
        # if no root id is given at creation time, there is no root directory
276
272
        inv = inventory.Inventory(root_id=None)
277
273
        self.assertIs(None, inv.root)
278
274
        # add a root entry by adding its path
279
 
        ie = inv.add_path(u"", "directory", b"my-root")
280
 
        ie.revision = b'test-rev'
281
 
        self.assertEqual(b"my-root", ie.file_id)
 
275
        ie = inv.add_path("", "directory", "my-root")
 
276
        ie.revision = 'test-rev'
 
277
        self.assertEqual("my-root", ie.file_id)
282
278
        self.assertIs(ie, inv.root)
283
279
 
284
280
    def test_add_path(self):
285
 
        inv = inventory.Inventory(root_id=b'tree_root')
286
 
        ie = inv.add_path(u'hello', 'file', b'hello-id')
287
 
        self.assertEqual(b'hello-id', ie.file_id)
 
281
        inv = inventory.Inventory(root_id='tree_root')
 
282
        ie = inv.add_path('hello', 'file', 'hello-id')
 
283
        self.assertEqual('hello-id', ie.file_id)
288
284
        self.assertEqual('file', ie.kind)
289
285
 
290
286
    def test_copy(self):
291
287
        """Make sure copy() works and creates a deep copy."""
292
 
        inv = inventory.Inventory(root_id=b'some-tree-root')
293
 
        ie = inv.add_path(u'hello', 'file', b'hello-id')
 
288
        inv = inventory.Inventory(root_id='some-tree-root')
 
289
        ie = inv.add_path('hello', 'file', 'hello-id')
294
290
        inv2 = inv.copy()
295
 
        inv.root.file_id = b'some-new-root'
296
 
        ie.name = u'file2'
297
 
        self.assertEqual(b'some-tree-root', inv2.root.file_id)
298
 
        self.assertEqual(u'hello', inv2.get_entry(b'hello-id').name)
 
291
        inv.root.file_id = 'some-new-root'
 
292
        ie.name = 'file2'
 
293
        self.assertEqual('some-tree-root', inv2.root.file_id)
 
294
        self.assertEqual('hello', inv2['hello-id'].name)
299
295
 
300
296
    def test_copy_empty(self):
301
297
        """Make sure an empty inventory can be copied."""
305
301
 
306
302
    def test_copy_copies_root_revision(self):
307
303
        """Make sure the revision of the root gets copied."""
308
 
        inv = inventory.Inventory(root_id=b'someroot')
309
 
        inv.root.revision = b'therev'
 
304
        inv = inventory.Inventory(root_id='someroot')
 
305
        inv.root.revision = 'therev'
310
306
        inv2 = inv.copy()
311
 
        self.assertEqual(b'someroot', inv2.root.file_id)
312
 
        self.assertEqual(b'therev', inv2.root.revision)
 
307
        self.assertEquals('someroot', inv2.root.file_id)
 
308
        self.assertEquals('therev', inv2.root.revision)
313
309
 
314
310
    def test_create_tree_reference(self):
315
 
        inv = inventory.Inventory(b'tree-root-123')
316
 
        inv.add(TreeReference(
317
 
            b'nested-id', 'nested', parent_id=b'tree-root-123',
318
 
            revision=b'rev', reference_revision=b'rev2'))
 
311
        inv = inventory.Inventory('tree-root-123')
 
312
        inv.add(TreeReference('nested-id', 'nested', parent_id='tree-root-123',
 
313
                              revision='rev', reference_revision='rev2'))
319
314
 
320
315
    def test_error_encoding(self):
321
 
        inv = inventory.Inventory(b'tree-root')
322
 
        inv.add(InventoryFile(b'a-id', u'\u1234', b'tree-root'))
 
316
        inv = inventory.Inventory('tree-root')
 
317
        inv.add(InventoryFile('a-id', u'\u1234', 'tree-root'))
323
318
        e = self.assertRaises(errors.InconsistentDelta, inv.add,
324
 
                              InventoryFile(b'b-id', u'\u1234', b'tree-root'))
325
 
        self.assertContainsRe(str(e), '\\u1234')
 
319
            InventoryFile('b-id', u'\u1234', 'tree-root'))
 
320
        self.assertContainsRe(str(e), r'\\u1234')
326
321
 
327
322
    def test_add_recursive(self):
328
 
        parent = InventoryDirectory(b'src-id', 'src', b'tree-root')
329
 
        child = InventoryFile(b'hello-id', 'hello.c', b'src-id')
 
323
        parent = InventoryDirectory('src-id', 'src', 'tree-root')
 
324
        child = InventoryFile('hello-id', 'hello.c', 'src-id')
330
325
        parent.children[child.file_id] = child
331
 
        inv = inventory.Inventory(b'tree-root')
 
326
        inv = inventory.Inventory('tree-root')
332
327
        inv.add(parent)
333
 
        self.assertEqual('src/hello.c', inv.id2path(b'hello-id'))
 
328
        self.assertEqual('src/hello.c', inv.id2path('hello-id'))
 
329
 
334
330
 
335
331
 
336
332
class TestDeltaApplication(TestCaseWithTransport):
337
 
 
338
 
    scenarios = delta_application_scenarios()
339
 
 
 
333
 
340
334
    def get_empty_inventory(self, reference_inv=None):
341
335
        """Get an empty inventory.
342
336
 
353
347
        if reference_inv is not None:
354
348
            inv.root.revision = reference_inv.root.revision
355
349
        else:
356
 
            inv.root.revision = b'basis'
 
350
            inv.root.revision = 'basis'
357
351
        return inv
358
352
 
359
 
    def make_file_ie(self, file_id=b'file-id', name='name', parent_id=None):
360
 
        ie_file = inventory.InventoryFile(file_id, name, parent_id)
361
 
        ie_file.revision = b'result'
362
 
        ie_file.text_size = 0
363
 
        ie_file.text_sha1 = b''
364
 
        return ie_file
365
 
 
366
353
    def test_empty_delta(self):
367
354
        inv = self.get_empty_inventory()
368
355
        delta = []
372
359
 
373
360
    def test_None_file_id(self):
374
361
        inv = self.get_empty_inventory()
375
 
        dir1 = inventory.InventoryDirectory(b'dirid', 'dir1', inv.root.file_id)
376
 
        dir1.file_id = None
377
 
        dir1.revision = b'result'
 
362
        dir1 = inventory.InventoryDirectory(None, 'dir1', inv.root.file_id)
 
363
        dir1.revision = 'result'
378
364
        delta = [(None, u'dir1', None, dir1)]
379
365
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
380
 
                          inv, delta)
 
366
            inv, delta)
381
367
 
382
368
    def test_unicode_file_id(self):
383
369
        inv = self.get_empty_inventory()
384
 
        dir1 = inventory.InventoryDirectory(b'dirid', 'dir1', inv.root.file_id)
385
 
        dir1.file_id = u'dirid'
386
 
        dir1.revision = b'result'
 
370
        dir1 = inventory.InventoryDirectory(u'dirid', 'dir1', inv.root.file_id)
 
371
        dir1.revision = 'result'
387
372
        delta = [(None, u'dir1', dir1.file_id, dir1)]
388
373
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
389
 
                          inv, delta)
 
374
            inv, delta)
390
375
 
391
376
    def test_repeated_file_id(self):
392
377
        inv = self.get_empty_inventory()
393
 
        file1 = inventory.InventoryFile(b'id', 'path1', inv.root.file_id)
394
 
        file1.revision = b'result'
 
378
        file1 = inventory.InventoryFile('id', 'path1', inv.root.file_id)
 
379
        file1.revision = 'result'
395
380
        file1.text_size = 0
396
 
        file1.text_sha1 = b""
397
 
        file2 = file1.copy()
398
 
        file2.name = 'path2'
399
 
        delta = [(None, u'path1', b'id', file1),
400
 
                 (None, u'path2', b'id', file2)]
 
381
        file1.text_sha1 = ""
 
382
        file2 = inventory.InventoryFile('id', 'path2', inv.root.file_id)
 
383
        file2.revision = 'result'
 
384
        file2.text_size = 0
 
385
        file2.text_sha1 = ""
 
386
        delta = [(None, u'path1', 'id', file1), (None, u'path2', 'id', file2)]
401
387
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
402
 
                          inv, delta)
 
388
            inv, delta)
403
389
 
404
390
    def test_repeated_new_path(self):
405
391
        inv = self.get_empty_inventory()
406
 
        file1 = inventory.InventoryFile(b'id1', 'path', inv.root.file_id)
407
 
        file1.revision = b'result'
 
392
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
393
        file1.revision = 'result'
408
394
        file1.text_size = 0
409
 
        file1.text_sha1 = b""
410
 
        file2 = file1.copy()
411
 
        file2.file_id = b'id2'
412
 
        delta = [(None, u'path', b'id1', file1),
413
 
                 (None, u'path', b'id2', file2)]
 
395
        file1.text_sha1 = ""
 
396
        file2 = inventory.InventoryFile('id2', 'path', inv.root.file_id)
 
397
        file2.revision = 'result'
 
398
        file2.text_size = 0
 
399
        file2.text_sha1 = ""
 
400
        delta = [(None, u'path', 'id1', file1), (None, u'path', 'id2', file2)]
414
401
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
415
 
                          inv, delta)
 
402
            inv, delta)
416
403
 
417
404
    def test_repeated_old_path(self):
418
405
        inv = self.get_empty_inventory()
419
 
        file1 = inventory.InventoryFile(b'id1', 'path', inv.root.file_id)
420
 
        file1.revision = b'result'
 
406
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
407
        file1.revision = 'result'
421
408
        file1.text_size = 0
422
 
        file1.text_sha1 = b""
 
409
        file1.text_sha1 = ""
423
410
        # We can't *create* a source inventory with the same path, but
424
411
        # a badly generated partial delta might claim the same source twice.
425
412
        # This would be buggy in two ways: the path is repeated in the delta,
426
413
        # And the path for one of the file ids doesn't match the source
427
414
        # location. Alternatively, we could have a repeated fileid, but that
428
415
        # is separately checked for.
429
 
        file2 = inventory.InventoryFile(b'id2', 'path2', inv.root.file_id)
430
 
        file2.revision = b'result'
 
416
        file2 = inventory.InventoryFile('id2', 'path2', inv.root.file_id)
 
417
        file2.revision = 'result'
431
418
        file2.text_size = 0
432
 
        file2.text_sha1 = b""
 
419
        file2.text_sha1 = ""
433
420
        inv.add(file1)
434
421
        inv.add(file2)
435
 
        delta = [(u'path', None, b'id1', None), (u'path', None, b'id2', None)]
 
422
        delta = [(u'path', None, 'id1', None), (u'path', None, 'id2', None)]
436
423
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
437
 
                          inv, delta)
 
424
            inv, delta)
438
425
 
439
426
    def test_mismatched_id_entry_id(self):
440
427
        inv = self.get_empty_inventory()
441
 
        file1 = inventory.InventoryFile(b'id1', 'path', inv.root.file_id)
442
 
        file1.revision = b'result'
 
428
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
429
        file1.revision = 'result'
443
430
        file1.text_size = 0
444
 
        file1.text_sha1 = b""
445
 
        delta = [(None, u'path', b'id', file1)]
 
431
        file1.text_sha1 = ""
 
432
        delta = [(None, u'path', 'id', file1)]
446
433
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
447
 
                          inv, delta)
 
434
            inv, delta)
448
435
 
449
436
    def test_mismatched_new_path_entry_None(self):
450
437
        inv = self.get_empty_inventory()
451
 
        delta = [(None, u'path', b'id', None)]
 
438
        delta = [(None, u'path', 'id', None)]
452
439
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
453
 
                          inv, delta)
 
440
            inv, delta)
454
441
 
455
442
    def test_mismatched_new_path_None_entry(self):
456
443
        inv = self.get_empty_inventory()
457
 
        file1 = inventory.InventoryFile(b'id1', 'path', inv.root.file_id)
458
 
        file1.revision = b'result'
 
444
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
445
        file1.revision = 'result'
459
446
        file1.text_size = 0
460
 
        file1.text_sha1 = b""
461
 
        delta = [(u"path", None, b'id1', file1)]
 
447
        file1.text_sha1 = ""
 
448
        delta = [(u"path", None, 'id1', file1)]
462
449
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
463
 
                          inv, delta)
 
450
            inv, delta)
464
451
 
465
452
    def test_parent_is_not_directory(self):
466
453
        inv = self.get_empty_inventory()
467
 
        file1 = inventory.InventoryFile(b'id1', 'path', inv.root.file_id)
468
 
        file1.revision = b'result'
 
454
        file1 = inventory.InventoryFile('id1', 'path', inv.root.file_id)
 
455
        file1.revision = 'result'
469
456
        file1.text_size = 0
470
 
        file1.text_sha1 = b""
471
 
        file2 = inventory.InventoryFile(b'id2', 'path2', b'id1')
472
 
        file2.revision = b'result'
 
457
        file1.text_sha1 = ""
 
458
        file2 = inventory.InventoryFile('id2', 'path2', 'id1')
 
459
        file2.revision = 'result'
473
460
        file2.text_size = 0
474
 
        file2.text_sha1 = b""
 
461
        file2.text_sha1 = ""
475
462
        inv.add(file1)
476
 
        delta = [(None, u'path/path2', b'id2', file2)]
 
463
        delta = [(None, u'path/path2', 'id2', file2)]
477
464
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
478
 
                          inv, delta)
 
465
            inv, delta)
479
466
 
480
467
    def test_parent_is_missing(self):
481
468
        inv = self.get_empty_inventory()
482
 
        file2 = inventory.InventoryFile(b'id2', 'path2', b'missingparent')
483
 
        file2.revision = b'result'
 
469
        file2 = inventory.InventoryFile('id2', 'path2', 'missingparent')
 
470
        file2.revision = 'result'
484
471
        file2.text_size = 0
485
 
        file2.text_sha1 = b""
486
 
        delta = [(None, u'path/path2', b'id2', file2)]
 
472
        file2.text_sha1 = ""
 
473
        delta = [(None, u'path/path2', 'id2', file2)]
487
474
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
488
 
                          inv, delta)
 
475
            inv, delta)
489
476
 
490
477
    def test_new_parent_path_has_wrong_id(self):
491
478
        inv = self.get_empty_inventory()
492
 
        parent1 = inventory.InventoryDirectory(b'p-1', 'dir', inv.root.file_id)
493
 
        parent1.revision = b'result'
494
 
        parent2 = inventory.InventoryDirectory(
495
 
            b'p-2', 'dir2', inv.root.file_id)
496
 
        parent2.revision = b'result'
497
 
        file1 = inventory.InventoryFile(b'id', 'path', b'p-2')
498
 
        file1.revision = b'result'
 
479
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
 
480
        parent1.revision = 'result'
 
481
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
 
482
        parent2.revision = 'result'
 
483
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
 
484
        file1.revision = 'result'
499
485
        file1.text_size = 0
500
 
        file1.text_sha1 = b""
 
486
        file1.text_sha1 = ""
501
487
        inv.add(parent1)
502
488
        inv.add(parent2)
503
489
        # This delta claims that file1 is at dir/path, but actually its at
504
490
        # dir2/path if you follow the inventory parent structure.
505
 
        delta = [(None, u'dir/path', b'id', file1)]
 
491
        delta = [(None, u'dir/path', 'id', file1)]
506
492
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
507
 
                          inv, delta)
 
493
            inv, delta)
508
494
 
509
495
    def test_old_parent_path_is_wrong(self):
510
496
        inv = self.get_empty_inventory()
511
 
        parent1 = inventory.InventoryDirectory(b'p-1', 'dir', inv.root.file_id)
512
 
        parent1.revision = b'result'
513
 
        parent2 = inventory.InventoryDirectory(
514
 
            b'p-2', 'dir2', inv.root.file_id)
515
 
        parent2.revision = b'result'
516
 
        file1 = inventory.InventoryFile(b'id', 'path', b'p-2')
517
 
        file1.revision = b'result'
 
497
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
 
498
        parent1.revision = 'result'
 
499
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
 
500
        parent2.revision = 'result'
 
501
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
 
502
        file1.revision = 'result'
518
503
        file1.text_size = 0
519
 
        file1.text_sha1 = b""
 
504
        file1.text_sha1 = ""
520
505
        inv.add(parent1)
521
506
        inv.add(parent2)
522
507
        inv.add(file1)
523
508
        # This delta claims that file1 was at dir/path, but actually it was at
524
509
        # dir2/path if you follow the inventory parent structure.
525
 
        delta = [(u'dir/path', None, b'id', None)]
 
510
        delta = [(u'dir/path', None, 'id', None)]
526
511
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
527
 
                          inv, delta)
 
512
            inv, delta)
528
513
 
529
514
    def test_old_parent_path_is_for_other_id(self):
530
515
        inv = self.get_empty_inventory()
531
 
        parent1 = inventory.InventoryDirectory(b'p-1', 'dir', inv.root.file_id)
532
 
        parent1.revision = b'result'
533
 
        parent2 = inventory.InventoryDirectory(
534
 
            b'p-2', 'dir2', inv.root.file_id)
535
 
        parent2.revision = b'result'
536
 
        file1 = inventory.InventoryFile(b'id', 'path', b'p-2')
537
 
        file1.revision = b'result'
 
516
        parent1 = inventory.InventoryDirectory('p-1', 'dir', inv.root.file_id)
 
517
        parent1.revision = 'result'
 
518
        parent2 = inventory.InventoryDirectory('p-2', 'dir2', inv.root.file_id)
 
519
        parent2.revision = 'result'
 
520
        file1 = inventory.InventoryFile('id', 'path', 'p-2')
 
521
        file1.revision = 'result'
538
522
        file1.text_size = 0
539
 
        file1.text_sha1 = b""
540
 
        file2 = inventory.InventoryFile(b'id2', 'path', b'p-1')
541
 
        file2.revision = b'result'
 
523
        file1.text_sha1 = ""
 
524
        file2 = inventory.InventoryFile('id2', 'path', 'p-1')
 
525
        file2.revision = 'result'
542
526
        file2.text_size = 0
543
 
        file2.text_sha1 = b""
 
527
        file2.text_sha1 = ""
544
528
        inv.add(parent1)
545
529
        inv.add(parent2)
546
530
        inv.add(file1)
548
532
        # This delta claims that file1 was at dir/path, but actually it was at
549
533
        # dir2/path if you follow the inventory parent structure. At dir/path
550
534
        # is another entry we should not delete.
551
 
        delta = [(u'dir/path', None, b'id', None)]
 
535
        delta = [(u'dir/path', None, 'id', None)]
552
536
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
553
 
                          inv, delta)
 
537
            inv, delta)
554
538
 
555
539
    def test_add_existing_id_new_path(self):
556
540
        inv = self.get_empty_inventory()
557
 
        parent1 = inventory.InventoryDirectory(
558
 
            b'p-1', 'dir1', inv.root.file_id)
559
 
        parent1.revision = b'result'
560
 
        parent2 = inventory.InventoryDirectory(
561
 
            b'p-1', 'dir2', inv.root.file_id)
562
 
        parent2.revision = b'result'
 
541
        parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
 
542
        parent1.revision = 'result'
 
543
        parent2 = inventory.InventoryDirectory('p-1', 'dir2', inv.root.file_id)
 
544
        parent2.revision = 'result'
563
545
        inv.add(parent1)
564
 
        delta = [(None, u'dir2', b'p-1', parent2)]
 
546
        delta = [(None, u'dir2', 'p-1', parent2)]
565
547
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
566
 
                          inv, delta)
 
548
            inv, delta)
567
549
 
568
550
    def test_add_new_id_existing_path(self):
569
551
        inv = self.get_empty_inventory()
570
 
        parent1 = inventory.InventoryDirectory(
571
 
            b'p-1', 'dir1', inv.root.file_id)
572
 
        parent1.revision = b'result'
573
 
        parent2 = inventory.InventoryDirectory(
574
 
            b'p-2', 'dir1', inv.root.file_id)
575
 
        parent2.revision = b'result'
 
552
        parent1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
 
553
        parent1.revision = 'result'
 
554
        parent2 = inventory.InventoryDirectory('p-2', 'dir1', inv.root.file_id)
 
555
        parent2.revision = 'result'
576
556
        inv.add(parent1)
577
 
        delta = [(None, u'dir1', b'p-2', parent2)]
 
557
        delta = [(None, u'dir1', 'p-2', parent2)]
578
558
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
579
 
                          inv, delta)
 
559
            inv, delta)
580
560
 
581
561
    def test_remove_dir_leaving_dangling_child(self):
582
562
        inv = self.get_empty_inventory()
583
 
        dir1 = inventory.InventoryDirectory(b'p-1', 'dir1', inv.root.file_id)
584
 
        dir1.revision = b'result'
585
 
        dir2 = inventory.InventoryDirectory(b'p-2', 'child1', b'p-1')
586
 
        dir2.revision = b'result'
587
 
        dir3 = inventory.InventoryDirectory(b'p-3', 'child2', b'p-1')
588
 
        dir3.revision = b'result'
 
563
        dir1 = inventory.InventoryDirectory('p-1', 'dir1', inv.root.file_id)
 
564
        dir1.revision = 'result'
 
565
        dir2 = inventory.InventoryDirectory('p-2', 'child1', 'p-1')
 
566
        dir2.revision = 'result'
 
567
        dir3 = inventory.InventoryDirectory('p-3', 'child2', 'p-1')
 
568
        dir3.revision = 'result'
589
569
        inv.add(dir1)
590
570
        inv.add(dir2)
591
571
        inv.add(dir3)
592
 
        delta = [(u'dir1', None, b'p-1', None),
593
 
                 (u'dir1/child2', None, b'p-3', None)]
 
572
        delta = [(u'dir1', None, 'p-1', None),
 
573
            (u'dir1/child2', None, 'p-3', None)]
594
574
        self.assertRaises(errors.InconsistentDelta, self.apply_delta, self,
595
 
                          inv, delta)
596
 
 
597
 
    def test_add_file(self):
598
 
        inv = self.get_empty_inventory()
599
 
        file1 = inventory.InventoryFile(b'file-id', 'path', inv.root.file_id)
600
 
        file1.revision = b'result'
601
 
        file1.text_size = 0
602
 
        file1.text_sha1 = b''
603
 
        delta = [(None, u'path', b'file-id', file1)]
604
 
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
605
 
        self.assertEqual(b'file-id', res_inv.get_entry(b'file-id').file_id)
606
 
 
607
 
    def test_remove_file(self):
608
 
        inv = self.get_empty_inventory()
609
 
        file1 = inventory.InventoryFile(b'file-id', 'path', inv.root.file_id)
610
 
        file1.revision = b'result'
611
 
        file1.text_size = 0
612
 
        file1.text_sha1 = b''
613
 
        inv.add(file1)
614
 
        delta = [(u'path', None, b'file-id', None)]
615
 
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
616
 
        self.assertEqual(None, res_inv.path2id('path'))
617
 
        self.assertRaises(errors.NoSuchId, res_inv.id2path, b'file-id')
618
 
 
619
 
    def test_rename_file(self):
620
 
        inv = self.get_empty_inventory()
621
 
        file1 = self.make_file_ie(name='path', parent_id=inv.root.file_id)
622
 
        inv.add(file1)
623
 
        file2 = self.make_file_ie(name='path2', parent_id=inv.root.file_id)
624
 
        delta = [(u'path', 'path2', b'file-id', file2)]
625
 
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
626
 
        self.assertEqual(None, res_inv.path2id('path'))
627
 
        self.assertEqual(b'file-id', res_inv.path2id('path2'))
628
 
 
629
 
    def test_replaced_at_new_path(self):
630
 
        inv = self.get_empty_inventory()
631
 
        file1 = self.make_file_ie(file_id=b'id1', parent_id=inv.root.file_id)
632
 
        inv.add(file1)
633
 
        file2 = self.make_file_ie(file_id=b'id2', parent_id=inv.root.file_id)
634
 
        delta = [(u'name', None, b'id1', None),
635
 
                 (None, u'name', b'id2', file2)]
636
 
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
637
 
        self.assertEqual(b'id2', res_inv.path2id('name'))
638
 
 
639
 
    def test_rename_dir(self):
640
 
        inv = self.get_empty_inventory()
641
 
        dir1 = inventory.InventoryDirectory(
642
 
            b'dir-id', 'dir1', inv.root.file_id)
643
 
        dir1.revision = b'basis'
644
 
        file1 = self.make_file_ie(parent_id=b'dir-id')
645
 
        inv.add(dir1)
646
 
        inv.add(file1)
647
 
        dir2 = inventory.InventoryDirectory(
648
 
            b'dir-id', 'dir2', inv.root.file_id)
649
 
        dir2.revision = b'result'
650
 
        delta = [('dir1', 'dir2', b'dir-id', dir2)]
651
 
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
652
 
        # The file should be accessible under the new path
653
 
        self.assertEqual(b'file-id', res_inv.path2id('dir2/name'))
654
 
 
655
 
    def test_renamed_dir_with_renamed_child(self):
656
 
        inv = self.get_empty_inventory()
657
 
        dir1 = inventory.InventoryDirectory(
658
 
            b'dir-id', 'dir1', inv.root.file_id)
659
 
        dir1.revision = b'basis'
660
 
        file1 = self.make_file_ie(b'file-id-1', 'name1', parent_id=b'dir-id')
661
 
        file2 = self.make_file_ie(b'file-id-2', 'name2', parent_id=b'dir-id')
662
 
        inv.add(dir1)
663
 
        inv.add(file1)
664
 
        inv.add(file2)
665
 
        dir2 = inventory.InventoryDirectory(
666
 
            b'dir-id', 'dir2', inv.root.file_id)
667
 
        dir2.revision = b'result'
668
 
        file2b = self.make_file_ie(b'file-id-2', 'name2', inv.root.file_id)
669
 
        delta = [('dir1', 'dir2', b'dir-id', dir2),
670
 
                 ('dir1/name2', 'name2', b'file-id-2', file2b)]
671
 
        res_inv = self.apply_delta(self, inv, delta, invalid_delta=False)
672
 
        # The file should be accessible under the new path
673
 
        self.assertEqual(b'file-id-1', res_inv.path2id('dir2/name1'))
674
 
        self.assertEqual(None, res_inv.path2id('dir2/name2'))
675
 
        self.assertEqual(b'file-id-2', res_inv.path2id('name2'))
 
575
            inv, delta)
 
576
 
 
577
 
 
578
class TestInventory(TestCase):
676
579
 
677
580
    def test_is_root(self):
678
581
        """Ensure our root-checking code is accurate."""
679
 
        inv = inventory.Inventory(b'TREE_ROOT')
680
 
        self.assertTrue(inv.is_root(b'TREE_ROOT'))
681
 
        self.assertFalse(inv.is_root(b'booga'))
682
 
        inv.root.file_id = b'booga'
683
 
        self.assertFalse(inv.is_root(b'TREE_ROOT'))
684
 
        self.assertTrue(inv.is_root(b'booga'))
 
582
        inv = inventory.Inventory('TREE_ROOT')
 
583
        self.assertTrue(inv.is_root('TREE_ROOT'))
 
584
        self.assertFalse(inv.is_root('booga'))
 
585
        inv.root.file_id = 'booga'
 
586
        self.assertFalse(inv.is_root('TREE_ROOT'))
 
587
        self.assertTrue(inv.is_root('booga'))
685
588
        # works properly even if no root is set
686
589
        inv.root = None
687
 
        self.assertFalse(inv.is_root(b'TREE_ROOT'))
688
 
        self.assertFalse(inv.is_root(b'booga'))
689
 
 
690
 
    def test_entries_for_empty_inventory(self):
691
 
        """Test that entries() will not fail for an empty inventory"""
692
 
        inv = Inventory(root_id=None)
693
 
        self.assertEqual([], inv.entries())
 
590
        self.assertFalse(inv.is_root('TREE_ROOT'))
 
591
        self.assertFalse(inv.is_root('booga'))
694
592
 
695
593
 
696
594
class TestInventoryEntry(TestCase):
697
595
 
698
 
    def test_file_invalid_entry_name(self):
699
 
        self.assertRaises(errors.InvalidEntryName, inventory.InventoryFile,
700
 
                          b'123', 'a/hello.c', ROOT_ID)
701
 
 
702
 
    def test_file_backslash(self):
703
 
        file = inventory.InventoryFile(b'123', 'h\\ello.c', ROOT_ID)
704
 
        self.assertEquals(file.name, 'h\\ello.c')
705
 
 
706
596
    def test_file_kind_character(self):
707
 
        file = inventory.InventoryFile(b'123', 'hello.c', ROOT_ID)
 
597
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
708
598
        self.assertEqual(file.kind_character(), '')
709
599
 
710
600
    def test_dir_kind_character(self):
711
 
        dir = inventory.InventoryDirectory(b'123', 'hello.c', ROOT_ID)
 
601
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
712
602
        self.assertEqual(dir.kind_character(), '/')
713
603
 
714
604
    def test_link_kind_character(self):
715
 
        dir = inventory.InventoryLink(b'123', 'hello.c', ROOT_ID)
 
605
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
716
606
        self.assertEqual(dir.kind_character(), '')
717
607
 
718
 
    def test_link_kind_character(self):
719
 
        dir = TreeReference(b'123', 'hello.c', ROOT_ID)
720
 
        self.assertEqual(dir.kind_character(), '+')
721
 
 
722
608
    def test_dir_detect_changes(self):
723
 
        left = inventory.InventoryDirectory(b'123', 'hello.c', ROOT_ID)
724
 
        right = inventory.InventoryDirectory(b'123', 'hello.c', ROOT_ID)
 
609
        left = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
610
        left.text_sha1 = 123
 
611
        left.executable = True
 
612
        left.symlink_target='foo'
 
613
        right = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
614
        right.text_sha1 = 321
 
615
        right.symlink_target='bar'
725
616
        self.assertEqual((False, False), left.detect_changes(right))
726
617
        self.assertEqual((False, False), right.detect_changes(left))
727
618
 
728
619
    def test_file_detect_changes(self):
729
 
        left = inventory.InventoryFile(b'123', 'hello.c', ROOT_ID)
 
620
        left = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
730
621
        left.text_sha1 = 123
731
 
        right = inventory.InventoryFile(b'123', 'hello.c', ROOT_ID)
 
622
        right = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
732
623
        right.text_sha1 = 123
733
624
        self.assertEqual((False, False), left.detect_changes(right))
734
625
        self.assertEqual((False, False), right.detect_changes(left))
740
631
        self.assertEqual((True, True), right.detect_changes(left))
741
632
 
742
633
    def test_symlink_detect_changes(self):
743
 
        left = inventory.InventoryLink(b'123', 'hello.c', ROOT_ID)
744
 
        left.symlink_target = 'foo'
745
 
        right = inventory.InventoryLink(b'123', 'hello.c', ROOT_ID)
746
 
        right.symlink_target = 'foo'
 
634
        left = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
635
        left.text_sha1 = 123
 
636
        left.executable = True
 
637
        left.symlink_target='foo'
 
638
        right = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
639
        right.text_sha1 = 321
 
640
        right.symlink_target='foo'
747
641
        self.assertEqual((False, False), left.detect_changes(right))
748
642
        self.assertEqual((False, False), right.detect_changes(left))
749
643
        left.symlink_target = 'different'
751
645
        self.assertEqual((True, False), right.detect_changes(left))
752
646
 
753
647
    def test_file_has_text(self):
754
 
        file = inventory.InventoryFile(b'123', 'hello.c', ROOT_ID)
755
 
        self.assertTrue(file.has_text())
 
648
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
649
        self.failUnless(file.has_text())
756
650
 
757
651
    def test_directory_has_text(self):
758
 
        dir = inventory.InventoryDirectory(b'123', 'hello.c', ROOT_ID)
759
 
        self.assertFalse(dir.has_text())
 
652
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
653
        self.failIf(dir.has_text())
760
654
 
761
655
    def test_link_has_text(self):
762
 
        link = inventory.InventoryLink(b'123', 'hello.c', ROOT_ID)
763
 
        self.assertFalse(link.has_text())
 
656
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
657
        self.failIf(link.has_text())
764
658
 
765
659
    def test_make_entry(self):
766
660
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
767
 
                              inventory.InventoryFile)
 
661
            inventory.InventoryFile)
768
662
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
769
 
                              inventory.InventoryLink)
 
663
            inventory.InventoryLink)
770
664
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
771
 
                              inventory.InventoryDirectory)
 
665
            inventory.InventoryDirectory)
772
666
 
773
667
    def test_make_entry_non_normalized(self):
774
668
        orig_normalized_filename = osutils.normalized_filename
781
675
 
782
676
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
783
677
            self.assertRaises(errors.InvalidNormalization,
784
 
                              inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
 
678
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
785
679
        finally:
786
680
            osutils.normalized_filename = orig_normalized_filename
787
681
 
798
692
        # renamed/reparented and modified
799
693
        # change kind (perhaps can't be done yet?)
800
694
        # also, merged in combination with all of these?
801
 
        old_a = InventoryFile(b'a-id', 'a_file', ROOT_ID)
802
 
        old_a.text_sha1 = b'123132'
 
695
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
696
        old_a.text_sha1 = '123132'
803
697
        old_a.text_size = 0
804
 
        new_a = InventoryFile(b'a-id', 'a_file', ROOT_ID)
805
 
        new_a.text_sha1 = b'123132'
 
698
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
699
        new_a.text_sha1 = '123132'
806
700
        new_a.text_size = 0
807
701
 
808
702
        self.assertChangeDescription('unchanged', old_a, new_a)
809
703
 
810
704
        new_a.text_size = 10
811
 
        new_a.text_sha1 = b'abcabc'
 
705
        new_a.text_sha1 = 'abcabc'
812
706
        self.assertChangeDescription('modified', old_a, new_a)
813
707
 
814
708
        self.assertChangeDescription('added', None, new_a)
823
717
 
824
718
        # reparenting is 'renaming'
825
719
        new_a.name = old_a.name
826
 
        new_a.parent_id = b'somedir-id'
 
720
        new_a.parent_id = 'somedir-id'
827
721
        self.assertChangeDescription('modified and renamed', old_a, new_a)
828
722
 
829
723
        # reset the content values so its not modified
836
730
 
837
731
        # reparenting is 'renaming'
838
732
        new_a.name = old_a.name
839
 
        new_a.parent_id = b'somedir-id'
 
733
        new_a.parent_id = 'somedir-id'
840
734
        self.assertChangeDescription('renamed', old_a, new_a)
841
735
 
842
736
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
853
747
 
854
748
    def read_bytes(self, chk_bytes, key):
855
749
        stream = chk_bytes.get_record_stream([key], 'unordered', True)
856
 
        return next(stream).get_bytes_as("fulltext")
 
750
        return stream.next().get_bytes_as("fulltext")
857
751
 
858
752
    def test_deserialise_gives_CHKInventory(self):
859
753
        inv = Inventory()
860
 
        inv.revision_id = b"revid"
861
 
        inv.root.revision = b"rootrev"
 
754
        inv.revision_id = "revid"
 
755
        inv.root.revision = "rootrev"
862
756
        chk_bytes = self.get_chk_bytes()
863
757
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
864
 
        lines = chk_inv.to_lines()
865
 
        new_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
866
 
        self.assertEqual(b"revid", new_inv.revision_id)
 
758
        bytes = ''.join(chk_inv.to_lines())
 
759
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
760
        self.assertEqual("revid", new_inv.revision_id)
867
761
        self.assertEqual("directory", new_inv.root.kind)
868
762
        self.assertEqual(inv.root.file_id, new_inv.root.file_id)
869
763
        self.assertEqual(inv.root.parent_id, new_inv.root.parent_id)
870
764
        self.assertEqual(inv.root.name, new_inv.root.name)
871
 
        self.assertEqual(b"rootrev", new_inv.root.revision)
872
 
        self.assertEqual(b'plain', new_inv._search_key_name)
 
765
        self.assertEqual("rootrev", new_inv.root.revision)
 
766
        self.assertEqual('plain', new_inv._search_key_name)
873
767
 
874
768
    def test_deserialise_wrong_revid(self):
875
769
        inv = Inventory()
876
 
        inv.revision_id = b"revid"
877
 
        inv.root.revision = b"rootrev"
 
770
        inv.revision_id = "revid"
 
771
        inv.root.revision = "rootrev"
878
772
        chk_bytes = self.get_chk_bytes()
879
773
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
880
 
        lines = chk_inv.to_lines()
 
774
        bytes = ''.join(chk_inv.to_lines())
881
775
        self.assertRaises(ValueError, CHKInventory.deserialise, chk_bytes,
882
 
                          lines, (b"revid2",))
 
776
            bytes, ("revid2",))
883
777
 
884
778
    def test_captures_rev_root_byid(self):
885
779
        inv = Inventory()
886
 
        inv.revision_id = b"foo"
887
 
        inv.root.revision = b"bar"
 
780
        inv.revision_id = "foo"
 
781
        inv.root.revision = "bar"
888
782
        chk_bytes = self.get_chk_bytes()
889
783
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
890
784
        lines = chk_inv.to_lines()
891
785
        self.assertEqual([
892
 
            b'chkinventory:\n',
893
 
            b'revision_id: foo\n',
894
 
            b'root_id: TREE_ROOT\n',
895
 
            b'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
896
 
            b'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
 
786
            'chkinventory:\n',
 
787
            'revision_id: foo\n',
 
788
            'root_id: TREE_ROOT\n',
 
789
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
 
790
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
897
791
            ], lines)
898
 
        chk_inv = CHKInventory.deserialise(
899
 
            chk_bytes, lines, (b'foo',))
900
 
        self.assertEqual(b'plain', chk_inv._search_key_name)
 
792
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
 
793
        self.assertEqual('plain', chk_inv._search_key_name)
901
794
 
902
795
    def test_captures_parent_id_basename_index(self):
903
796
        inv = Inventory()
904
 
        inv.revision_id = b"foo"
905
 
        inv.root.revision = b"bar"
 
797
        inv.revision_id = "foo"
 
798
        inv.root.revision = "bar"
906
799
        chk_bytes = self.get_chk_bytes()
907
800
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
908
801
        lines = chk_inv.to_lines()
909
802
        self.assertEqual([
910
 
            b'chkinventory:\n',
911
 
            b'revision_id: foo\n',
912
 
            b'root_id: TREE_ROOT\n',
913
 
            b'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
914
 
            b'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
 
803
            'chkinventory:\n',
 
804
            'revision_id: foo\n',
 
805
            'root_id: TREE_ROOT\n',
 
806
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
 
807
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
915
808
            ], lines)
916
 
        chk_inv = CHKInventory.deserialise(
917
 
            chk_bytes, lines, (b'foo',))
918
 
        self.assertEqual(b'plain', chk_inv._search_key_name)
 
809
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
 
810
        self.assertEqual('plain', chk_inv._search_key_name)
919
811
 
920
812
    def test_captures_search_key_name(self):
921
813
        inv = Inventory()
922
 
        inv.revision_id = b"foo"
923
 
        inv.root.revision = b"bar"
 
814
        inv.revision_id = "foo"
 
815
        inv.root.revision = "bar"
924
816
        chk_bytes = self.get_chk_bytes()
925
817
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
926
 
                                              search_key_name=b'hash-16-way')
 
818
                                              search_key_name='hash-16-way')
927
819
        lines = chk_inv.to_lines()
928
820
        self.assertEqual([
929
 
            b'chkinventory:\n',
930
 
            b'search_key_name: hash-16-way\n',
931
 
            b'root_id: TREE_ROOT\n',
932
 
            b'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
933
 
            b'revision_id: foo\n',
934
 
            b'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
 
821
            'chkinventory:\n',
 
822
            'search_key_name: hash-16-way\n',
 
823
            'root_id: TREE_ROOT\n',
 
824
            'parent_id_basename_to_file_id: sha1:eb23f0ad4b07f48e88c76d4c94292be57fb2785f\n',
 
825
            'revision_id: foo\n',
 
826
            'id_to_entry: sha1:debfe920f1f10e7929260f0534ac9a24d7aabbb4\n',
935
827
            ], lines)
936
 
        chk_inv = CHKInventory.deserialise(
937
 
            chk_bytes, lines, (b'foo',))
938
 
        self.assertEqual(b'hash-16-way', chk_inv._search_key_name)
 
828
        chk_inv = CHKInventory.deserialise(chk_bytes, ''.join(lines), ('foo',))
 
829
        self.assertEqual('hash-16-way', chk_inv._search_key_name)
939
830
 
940
831
    def test_directory_children_on_demand(self):
941
832
        inv = Inventory()
942
 
        inv.revision_id = b"revid"
943
 
        inv.root.revision = b"rootrev"
944
 
        inv.add(InventoryFile(b"fileid", "file", inv.root.file_id))
945
 
        inv.get_entry(b"fileid").revision = b"filerev"
946
 
        inv.get_entry(b"fileid").executable = True
947
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
948
 
        inv.get_entry(b"fileid").text_size = 1
 
833
        inv.revision_id = "revid"
 
834
        inv.root.revision = "rootrev"
 
835
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
836
        inv["fileid"].revision = "filerev"
 
837
        inv["fileid"].executable = True
 
838
        inv["fileid"].text_sha1 = "ffff"
 
839
        inv["fileid"].text_size = 1
949
840
        chk_bytes = self.get_chk_bytes()
950
841
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
951
 
        lines = chk_inv.to_lines()
952
 
        new_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
953
 
        root_entry = new_inv.get_entry(inv.root.file_id)
 
842
        bytes = ''.join(chk_inv.to_lines())
 
843
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
844
        root_entry = new_inv[inv.root.file_id]
954
845
        self.assertEqual(None, root_entry._children)
955
 
        self.assertEqual({'file'}, set(root_entry.children))
956
 
        file_direct = new_inv.get_entry(b"fileid")
 
846
        self.assertEqual(['file'], root_entry.children.keys())
 
847
        file_direct = new_inv["fileid"]
957
848
        file_found = root_entry.children['file']
958
849
        self.assertEqual(file_direct.kind, file_found.kind)
959
850
        self.assertEqual(file_direct.file_id, file_found.file_id)
967
858
    def test_from_inventory_maximum_size(self):
968
859
        # from_inventory supports the maximum_size parameter.
969
860
        inv = Inventory()
970
 
        inv.revision_id = b"revid"
971
 
        inv.root.revision = b"rootrev"
 
861
        inv.revision_id = "revid"
 
862
        inv.root.revision = "rootrev"
972
863
        chk_bytes = self.get_chk_bytes()
973
864
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv, 120)
974
865
        chk_inv.id_to_entry._ensure_root()
979
870
        self.assertEqual(120, p_id_basename._root_node.maximum_size)
980
871
        self.assertEqual(2, p_id_basename._root_node._key_width)
981
872
 
982
 
    def test_iter_all_ids(self):
 
873
    def test___iter__(self):
983
874
        inv = Inventory()
984
 
        inv.revision_id = b"revid"
985
 
        inv.root.revision = b"rootrev"
986
 
        inv.add(InventoryFile(b"fileid", "file", inv.root.file_id))
987
 
        inv.get_entry(b"fileid").revision = b"filerev"
988
 
        inv.get_entry(b"fileid").executable = True
989
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
990
 
        inv.get_entry(b"fileid").text_size = 1
 
875
        inv.revision_id = "revid"
 
876
        inv.root.revision = "rootrev"
 
877
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
878
        inv["fileid"].revision = "filerev"
 
879
        inv["fileid"].executable = True
 
880
        inv["fileid"].text_sha1 = "ffff"
 
881
        inv["fileid"].text_size = 1
991
882
        chk_bytes = self.get_chk_bytes()
992
883
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
993
 
        lines = chk_inv.to_lines()
994
 
        new_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
995
 
        fileids = sorted(new_inv.iter_all_ids())
996
 
        self.assertEqual([inv.root.file_id, b"fileid"], fileids)
 
884
        bytes = ''.join(chk_inv.to_lines())
 
885
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
886
        fileids = list(new_inv.__iter__())
 
887
        fileids.sort()
 
888
        self.assertEqual([inv.root.file_id, "fileid"], fileids)
997
889
 
998
890
    def test__len__(self):
999
891
        inv = Inventory()
1000
 
        inv.revision_id = b"revid"
1001
 
        inv.root.revision = b"rootrev"
1002
 
        inv.add(InventoryFile(b"fileid", "file", inv.root.file_id))
1003
 
        inv.get_entry(b"fileid").revision = b"filerev"
1004
 
        inv.get_entry(b"fileid").executable = True
1005
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1006
 
        inv.get_entry(b"fileid").text_size = 1
 
892
        inv.revision_id = "revid"
 
893
        inv.root.revision = "rootrev"
 
894
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
895
        inv["fileid"].revision = "filerev"
 
896
        inv["fileid"].executable = True
 
897
        inv["fileid"].text_sha1 = "ffff"
 
898
        inv["fileid"].text_size = 1
1007
899
        chk_bytes = self.get_chk_bytes()
1008
900
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1009
901
        self.assertEqual(2, len(chk_inv))
1010
902
 
1011
 
    def test_get_entry(self):
 
903
    def test___getitem__(self):
1012
904
        inv = Inventory()
1013
 
        inv.revision_id = b"revid"
1014
 
        inv.root.revision = b"rootrev"
1015
 
        inv.add(InventoryFile(b"fileid", u"file", inv.root.file_id))
1016
 
        inv.get_entry(b"fileid").revision = b"filerev"
1017
 
        inv.get_entry(b"fileid").executable = True
1018
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1019
 
        inv.get_entry(b"fileid").text_size = 1
 
905
        inv.revision_id = "revid"
 
906
        inv.root.revision = "rootrev"
 
907
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
908
        inv["fileid"].revision = "filerev"
 
909
        inv["fileid"].executable = True
 
910
        inv["fileid"].text_sha1 = "ffff"
 
911
        inv["fileid"].text_size = 1
1020
912
        chk_bytes = self.get_chk_bytes()
1021
913
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1022
 
        lines = chk_inv.to_lines()
1023
 
        new_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
1024
 
        root_entry = new_inv.get_entry(inv.root.file_id)
1025
 
        file_entry = new_inv.get_entry(b"fileid")
 
914
        bytes = ''.join(chk_inv.to_lines())
 
915
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
916
        root_entry = new_inv[inv.root.file_id]
 
917
        file_entry = new_inv["fileid"]
1026
918
        self.assertEqual("directory", root_entry.kind)
1027
919
        self.assertEqual(inv.root.file_id, root_entry.file_id)
1028
920
        self.assertEqual(inv.root.parent_id, root_entry.parent_id)
1029
921
        self.assertEqual(inv.root.name, root_entry.name)
1030
 
        self.assertEqual(b"rootrev", root_entry.revision)
 
922
        self.assertEqual("rootrev", root_entry.revision)
1031
923
        self.assertEqual("file", file_entry.kind)
1032
 
        self.assertEqual(b"fileid", file_entry.file_id)
 
924
        self.assertEqual("fileid", file_entry.file_id)
1033
925
        self.assertEqual(inv.root.file_id, file_entry.parent_id)
1034
 
        self.assertEqual(u"file", file_entry.name)
1035
 
        self.assertEqual(b"filerev", file_entry.revision)
1036
 
        self.assertEqual(b"ffff", file_entry.text_sha1)
 
926
        self.assertEqual("file", file_entry.name)
 
927
        self.assertEqual("filerev", file_entry.revision)
 
928
        self.assertEqual("ffff", file_entry.text_sha1)
1037
929
        self.assertEqual(1, file_entry.text_size)
1038
930
        self.assertEqual(True, file_entry.executable)
1039
 
        self.assertRaises(errors.NoSuchId, new_inv.get_entry, 'missing')
 
931
        self.assertRaises(errors.NoSuchId, new_inv.__getitem__, 'missing')
1040
932
 
1041
933
    def test_has_id_true(self):
1042
934
        inv = Inventory()
1043
 
        inv.revision_id = b"revid"
1044
 
        inv.root.revision = b"rootrev"
1045
 
        inv.add(InventoryFile(b"fileid", "file", inv.root.file_id))
1046
 
        inv.get_entry(b"fileid").revision = b"filerev"
1047
 
        inv.get_entry(b"fileid").executable = True
1048
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1049
 
        inv.get_entry(b"fileid").text_size = 1
 
935
        inv.revision_id = "revid"
 
936
        inv.root.revision = "rootrev"
 
937
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
938
        inv["fileid"].revision = "filerev"
 
939
        inv["fileid"].executable = True
 
940
        inv["fileid"].text_sha1 = "ffff"
 
941
        inv["fileid"].text_size = 1
1050
942
        chk_bytes = self.get_chk_bytes()
1051
943
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1052
 
        self.assertTrue(chk_inv.has_id(b'fileid'))
 
944
        self.assertTrue(chk_inv.has_id('fileid'))
1053
945
        self.assertTrue(chk_inv.has_id(inv.root.file_id))
1054
946
 
1055
947
    def test_has_id_not(self):
1056
948
        inv = Inventory()
1057
 
        inv.revision_id = b"revid"
1058
 
        inv.root.revision = b"rootrev"
 
949
        inv.revision_id = "revid"
 
950
        inv.root.revision = "rootrev"
1059
951
        chk_bytes = self.get_chk_bytes()
1060
952
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1061
 
        self.assertFalse(chk_inv.has_id(b'fileid'))
 
953
        self.assertFalse(chk_inv.has_id('fileid'))
1062
954
 
1063
955
    def test_id2path(self):
1064
956
        inv = Inventory()
1065
 
        inv.revision_id = b"revid"
1066
 
        inv.root.revision = b"rootrev"
1067
 
        direntry = InventoryDirectory(b"dirid", "dir", inv.root.file_id)
1068
 
        fileentry = InventoryFile(b"fileid", "file", b"dirid")
 
957
        inv.revision_id = "revid"
 
958
        inv.root.revision = "rootrev"
 
959
        direntry = InventoryDirectory("dirid", "dir", inv.root.file_id)
 
960
        fileentry = InventoryFile("fileid", "file", "dirid")
1069
961
        inv.add(direntry)
1070
962
        inv.add(fileentry)
1071
 
        inv.get_entry(b"fileid").revision = b"filerev"
1072
 
        inv.get_entry(b"fileid").executable = True
1073
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1074
 
        inv.get_entry(b"fileid").text_size = 1
1075
 
        inv.get_entry(b"dirid").revision = b"filerev"
 
963
        inv["fileid"].revision = "filerev"
 
964
        inv["fileid"].executable = True
 
965
        inv["fileid"].text_sha1 = "ffff"
 
966
        inv["fileid"].text_size = 1
 
967
        inv["dirid"].revision = "filerev"
1076
968
        chk_bytes = self.get_chk_bytes()
1077
969
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1078
 
        lines = chk_inv.to_lines()
1079
 
        new_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
 
970
        bytes = ''.join(chk_inv.to_lines())
 
971
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1080
972
        self.assertEqual('', new_inv.id2path(inv.root.file_id))
1081
 
        self.assertEqual('dir', new_inv.id2path(b'dirid'))
1082
 
        self.assertEqual('dir/file', new_inv.id2path(b'fileid'))
 
973
        self.assertEqual('dir', new_inv.id2path('dirid'))
 
974
        self.assertEqual('dir/file', new_inv.id2path('fileid'))
1083
975
 
1084
976
    def test_path2id(self):
1085
977
        inv = Inventory()
1086
 
        inv.revision_id = b"revid"
1087
 
        inv.root.revision = b"rootrev"
1088
 
        direntry = InventoryDirectory(b"dirid", "dir", inv.root.file_id)
1089
 
        fileentry = InventoryFile(b"fileid", "file", b"dirid")
 
978
        inv.revision_id = "revid"
 
979
        inv.root.revision = "rootrev"
 
980
        direntry = InventoryDirectory("dirid", "dir", inv.root.file_id)
 
981
        fileentry = InventoryFile("fileid", "file", "dirid")
1090
982
        inv.add(direntry)
1091
983
        inv.add(fileentry)
1092
 
        inv.get_entry(b"fileid").revision = b"filerev"
1093
 
        inv.get_entry(b"fileid").executable = True
1094
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1095
 
        inv.get_entry(b"fileid").text_size = 1
1096
 
        inv.get_entry(b"dirid").revision = b"filerev"
 
984
        inv["fileid"].revision = "filerev"
 
985
        inv["fileid"].executable = True
 
986
        inv["fileid"].text_sha1 = "ffff"
 
987
        inv["fileid"].text_size = 1
 
988
        inv["dirid"].revision = "filerev"
1097
989
        chk_bytes = self.get_chk_bytes()
1098
990
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1099
 
        lines = chk_inv.to_lines()
1100
 
        new_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
 
991
        bytes = ''.join(chk_inv.to_lines())
 
992
        new_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1101
993
        self.assertEqual(inv.root.file_id, new_inv.path2id(''))
1102
 
        self.assertEqual(b'dirid', new_inv.path2id('dir'))
1103
 
        self.assertEqual(b'fileid', new_inv.path2id('dir/file'))
 
994
        self.assertEqual('dirid', new_inv.path2id('dir'))
 
995
        self.assertEqual('fileid', new_inv.path2id('dir/file'))
1104
996
 
1105
997
    def test_create_by_apply_delta_sets_root(self):
1106
998
        inv = Inventory()
1107
 
        inv.root.revision = b"myrootrev"
1108
 
        inv.revision_id = b"revid"
 
999
        inv.revision_id = "revid"
1109
1000
        chk_bytes = self.get_chk_bytes()
1110
1001
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
1111
 
        inv.add_path("", "directory", b"myrootid", None)
1112
 
        inv.revision_id = b"expectedid"
1113
 
        inv.root.revision = b"myrootrev"
 
1002
        inv.add_path("", "directory", "myrootid", None)
 
1003
        inv.revision_id = "expectedid"
1114
1004
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
1115
1005
        delta = [("", None, base_inv.root.file_id, None),
1116
 
                 (None, "", b"myrootid", inv.root)]
1117
 
        new_inv = base_inv.create_by_apply_delta(delta, b"expectedid")
1118
 
        self.assertEqual(reference_inv.root, new_inv.root)
 
1006
            (None, "",  "myrootid", inv.root)]
 
1007
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
 
1008
        self.assertEquals(reference_inv.root, new_inv.root)
1119
1009
 
1120
1010
    def test_create_by_apply_delta_empty_add_child(self):
1121
1011
        inv = Inventory()
1122
 
        inv.revision_id = b"revid"
1123
 
        inv.root.revision = b"rootrev"
 
1012
        inv.revision_id = "revid"
 
1013
        inv.root.revision = "rootrev"
1124
1014
        chk_bytes = self.get_chk_bytes()
1125
1015
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
1126
 
        a_entry = InventoryFile(b"A-id", "A", inv.root.file_id)
1127
 
        a_entry.revision = b"filerev"
 
1016
        a_entry = InventoryFile("A-id", "A", inv.root.file_id)
 
1017
        a_entry.revision = "filerev"
1128
1018
        a_entry.executable = True
1129
 
        a_entry.text_sha1 = b"ffff"
 
1019
        a_entry.text_sha1 = "ffff"
1130
1020
        a_entry.text_size = 1
1131
1021
        inv.add(a_entry)
1132
 
        inv.revision_id = b"expectedid"
 
1022
        inv.revision_id = "expectedid"
1133
1023
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
1134
 
        delta = [(None, "A", b"A-id", a_entry)]
1135
 
        new_inv = base_inv.create_by_apply_delta(delta, b"expectedid")
 
1024
        delta = [(None, "A",  "A-id", a_entry)]
 
1025
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
1136
1026
        # new_inv should be the same as reference_inv.
1137
1027
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
1138
1028
        self.assertEqual(reference_inv.root_id, new_inv.root_id)
1139
1029
        reference_inv.id_to_entry._ensure_root()
1140
1030
        new_inv.id_to_entry._ensure_root()
1141
1031
        self.assertEqual(reference_inv.id_to_entry._root_node._key,
1142
 
                         new_inv.id_to_entry._root_node._key)
 
1032
            new_inv.id_to_entry._root_node._key)
1143
1033
 
1144
1034
    def test_create_by_apply_delta_empty_add_child_updates_parent_id(self):
1145
1035
        inv = Inventory()
1146
 
        inv.revision_id = b"revid"
1147
 
        inv.root.revision = b"rootrev"
 
1036
        inv.revision_id = "revid"
 
1037
        inv.root.revision = "rootrev"
1148
1038
        chk_bytes = self.get_chk_bytes()
1149
1039
        base_inv = CHKInventory.from_inventory(chk_bytes, inv)
1150
 
        a_entry = InventoryFile(b"A-id", "A", inv.root.file_id)
1151
 
        a_entry.revision = b"filerev"
 
1040
        a_entry = InventoryFile("A-id", "A", inv.root.file_id)
 
1041
        a_entry.revision = "filerev"
1152
1042
        a_entry.executable = True
1153
 
        a_entry.text_sha1 = b"ffff"
 
1043
        a_entry.text_sha1 = "ffff"
1154
1044
        a_entry.text_size = 1
1155
1045
        inv.add(a_entry)
1156
 
        inv.revision_id = b"expectedid"
 
1046
        inv.revision_id = "expectedid"
1157
1047
        reference_inv = CHKInventory.from_inventory(chk_bytes, inv)
1158
 
        delta = [(None, "A", b"A-id", a_entry)]
1159
 
        new_inv = base_inv.create_by_apply_delta(delta, b"expectedid")
 
1048
        delta = [(None, "A",  "A-id", a_entry)]
 
1049
        new_inv = base_inv.create_by_apply_delta(delta, "expectedid")
1160
1050
        reference_inv.id_to_entry._ensure_root()
1161
1051
        reference_inv.parent_id_basename_to_file_id._ensure_root()
1162
1052
        new_inv.id_to_entry._ensure_root()
1165
1055
        self.assertEqual(reference_inv.revision_id, new_inv.revision_id)
1166
1056
        self.assertEqual(reference_inv.root_id, new_inv.root_id)
1167
1057
        self.assertEqual(reference_inv.id_to_entry._root_node._key,
1168
 
                         new_inv.id_to_entry._root_node._key)
 
1058
            new_inv.id_to_entry._root_node._key)
1169
1059
        self.assertEqual(reference_inv.parent_id_basename_to_file_id._root_node._key,
1170
 
                         new_inv.parent_id_basename_to_file_id._root_node._key)
 
1060
            new_inv.parent_id_basename_to_file_id._root_node._key)
1171
1061
 
1172
1062
    def test_iter_changes(self):
1173
1063
        # Low level bootstrapping smoke test; comprehensive generic tests via
1174
1064
        # InterTree are coming.
1175
1065
        inv = Inventory()
1176
 
        inv.revision_id = b"revid"
1177
 
        inv.root.revision = b"rootrev"
1178
 
        inv.add(InventoryFile(b"fileid", "file", inv.root.file_id))
1179
 
        inv.get_entry(b"fileid").revision = b"filerev"
1180
 
        inv.get_entry(b"fileid").executable = True
1181
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1182
 
        inv.get_entry(b"fileid").text_size = 1
 
1066
        inv.revision_id = "revid"
 
1067
        inv.root.revision = "rootrev"
 
1068
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
1069
        inv["fileid"].revision = "filerev"
 
1070
        inv["fileid"].executable = True
 
1071
        inv["fileid"].text_sha1 = "ffff"
 
1072
        inv["fileid"].text_size = 1
1183
1073
        inv2 = Inventory()
1184
 
        inv2.revision_id = b"revid2"
1185
 
        inv2.root.revision = b"rootrev"
1186
 
        inv2.add(InventoryFile(b"fileid", "file", inv.root.file_id))
1187
 
        inv2.get_entry(b"fileid").revision = b"filerev2"
1188
 
        inv2.get_entry(b"fileid").executable = False
1189
 
        inv2.get_entry(b"fileid").text_sha1 = b"bbbb"
1190
 
        inv2.get_entry(b"fileid").text_size = 2
 
1074
        inv2.revision_id = "revid2"
 
1075
        inv2.root.revision = "rootrev"
 
1076
        inv2.add(InventoryFile("fileid", "file", inv.root.file_id))
 
1077
        inv2["fileid"].revision = "filerev2"
 
1078
        inv2["fileid"].executable = False
 
1079
        inv2["fileid"].text_sha1 = "bbbb"
 
1080
        inv2["fileid"].text_size = 2
1191
1081
        # get fresh objects.
1192
1082
        chk_bytes = self.get_chk_bytes()
1193
1083
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1194
 
        lines = chk_inv.to_lines()
1195
 
        inv_1 = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
 
1084
        bytes = ''.join(chk_inv.to_lines())
 
1085
        inv_1 = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1196
1086
        chk_inv2 = CHKInventory.from_inventory(chk_bytes, inv2)
1197
 
        lines = chk_inv2.to_lines()
1198
 
        inv_2 = CHKInventory.deserialise(chk_bytes, lines, (b"revid2",))
1199
 
        self.assertEqual([(b'fileid', (u'file', u'file'), True, (True, True),
1200
 
                           (b'TREE_ROOT', b'TREE_ROOT'), (u'file',
1201
 
                                                          u'file'), ('file', 'file'),
1202
 
                           (False, True))],
1203
 
                         list(inv_1.iter_changes(inv_2)))
 
1087
        bytes = ''.join(chk_inv2.to_lines())
 
1088
        inv_2 = CHKInventory.deserialise(chk_bytes, bytes, ("revid2",))
 
1089
        self.assertEqual([('fileid', (u'file', u'file'), True, (True, True),
 
1090
            ('TREE_ROOT', 'TREE_ROOT'), (u'file', u'file'), ('file', 'file'),
 
1091
            (False, True))],
 
1092
            list(inv_1.iter_changes(inv_2)))
1204
1093
 
1205
1094
    def test_parent_id_basename_to_file_id_index_enabled(self):
1206
1095
        inv = Inventory()
1207
 
        inv.revision_id = b"revid"
1208
 
        inv.root.revision = b"rootrev"
1209
 
        inv.add(InventoryFile(b"fileid", "file", inv.root.file_id))
1210
 
        inv.get_entry(b"fileid").revision = b"filerev"
1211
 
        inv.get_entry(b"fileid").executable = True
1212
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1213
 
        inv.get_entry(b"fileid").text_size = 1
 
1096
        inv.revision_id = "revid"
 
1097
        inv.root.revision = "rootrev"
 
1098
        inv.add(InventoryFile("fileid", "file", inv.root.file_id))
 
1099
        inv["fileid"].revision = "filerev"
 
1100
        inv["fileid"].executable = True
 
1101
        inv["fileid"].text_sha1 = "ffff"
 
1102
        inv["fileid"].text_size = 1
1214
1103
        # get fresh objects.
1215
1104
        chk_bytes = self.get_chk_bytes()
1216
1105
        tmp_inv = CHKInventory.from_inventory(chk_bytes, inv)
1217
 
        lines = tmp_inv.to_lines()
1218
 
        chk_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
1219
 
        self.assertIsInstance(
1220
 
            chk_inv.parent_id_basename_to_file_id, chk_map.CHKMap)
 
1106
        bytes = ''.join(tmp_inv.to_lines())
 
1107
        chk_inv = CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
 
1108
        self.assertIsInstance(chk_inv.parent_id_basename_to_file_id, chk_map.CHKMap)
1221
1109
        self.assertEqual(
1222
 
            {(b'', b''): b'TREE_ROOT', (b'TREE_ROOT', b'file'): b'fileid'},
 
1110
            {('', ''): 'TREE_ROOT', ('TREE_ROOT', 'file'): 'fileid'},
1223
1111
            dict(chk_inv.parent_id_basename_to_file_id.iteritems()))
1224
1112
 
1225
1113
    def test_file_entry_to_bytes(self):
1226
1114
        inv = CHKInventory(None)
1227
 
        ie = inventory.InventoryFile(b'file-id', 'filename', b'parent-id')
 
1115
        ie = inventory.InventoryFile('file-id', 'filename', 'parent-id')
1228
1116
        ie.executable = True
1229
 
        ie.revision = b'file-rev-id'
1230
 
        ie.text_sha1 = b'abcdefgh'
 
1117
        ie.revision = 'file-rev-id'
 
1118
        ie.text_sha1 = 'abcdefgh'
1231
1119
        ie.text_size = 100
1232
1120
        bytes = inv._entry_to_bytes(ie)
1233
 
        self.assertEqual(b'file: file-id\nparent-id\nfilename\n'
1234
 
                         b'file-rev-id\nabcdefgh\n100\nY', bytes)
 
1121
        self.assertEqual('file: file-id\nparent-id\nfilename\n'
 
1122
                         'file-rev-id\nabcdefgh\n100\nY', bytes)
1235
1123
        ie2 = inv._bytes_to_entry(bytes)
1236
1124
        self.assertEqual(ie, ie2)
1237
 
        self.assertIsInstance(ie2.name, text_type)
1238
 
        self.assertEqual((b'filename', b'file-id', b'file-rev-id'),
 
1125
        self.assertIsInstance(ie2.name, unicode)
 
1126
        self.assertEqual(('filename', 'file-id', 'file-rev-id'),
1239
1127
                         inv._bytes_to_utf8name_key(bytes))
1240
1128
 
1241
1129
    def test_file2_entry_to_bytes(self):
1242
1130
        inv = CHKInventory(None)
1243
1131
        # \u30a9 == 'omega'
1244
 
        ie = inventory.InventoryFile(b'file-id', u'\u03a9name', b'parent-id')
 
1132
        ie = inventory.InventoryFile('file-id', u'\u03a9name', 'parent-id')
1245
1133
        ie.executable = False
1246
 
        ie.revision = b'file-rev-id'
1247
 
        ie.text_sha1 = b'123456'
 
1134
        ie.revision = 'file-rev-id'
 
1135
        ie.text_sha1 = '123456'
1248
1136
        ie.text_size = 25
1249
1137
        bytes = inv._entry_to_bytes(ie)
1250
 
        self.assertEqual(b'file: file-id\nparent-id\n\xce\xa9name\n'
1251
 
                         b'file-rev-id\n123456\n25\nN', bytes)
 
1138
        self.assertEqual('file: file-id\nparent-id\n\xce\xa9name\n'
 
1139
                         'file-rev-id\n123456\n25\nN', bytes)
1252
1140
        ie2 = inv._bytes_to_entry(bytes)
1253
1141
        self.assertEqual(ie, ie2)
1254
 
        self.assertIsInstance(ie2.name, text_type)
1255
 
        self.assertEqual((b'\xce\xa9name', b'file-id', b'file-rev-id'),
 
1142
        self.assertIsInstance(ie2.name, unicode)
 
1143
        self.assertEqual(('\xce\xa9name', 'file-id', 'file-rev-id'),
1256
1144
                         inv._bytes_to_utf8name_key(bytes))
1257
1145
 
1258
1146
    def test_dir_entry_to_bytes(self):
1259
1147
        inv = CHKInventory(None)
1260
 
        ie = inventory.InventoryDirectory(b'dir-id', 'dirname', b'parent-id')
1261
 
        ie.revision = b'dir-rev-id'
 
1148
        ie = inventory.InventoryDirectory('dir-id', 'dirname', 'parent-id')
 
1149
        ie.revision = 'dir-rev-id'
1262
1150
        bytes = inv._entry_to_bytes(ie)
1263
 
        self.assertEqual(b'dir: dir-id\nparent-id\ndirname\ndir-rev-id', bytes)
 
1151
        self.assertEqual('dir: dir-id\nparent-id\ndirname\ndir-rev-id', bytes)
1264
1152
        ie2 = inv._bytes_to_entry(bytes)
1265
1153
        self.assertEqual(ie, ie2)
1266
 
        self.assertIsInstance(ie2.name, text_type)
1267
 
        self.assertEqual((b'dirname', b'dir-id', b'dir-rev-id'),
 
1154
        self.assertIsInstance(ie2.name, unicode)
 
1155
        self.assertEqual(('dirname', 'dir-id', 'dir-rev-id'),
1268
1156
                         inv._bytes_to_utf8name_key(bytes))
1269
1157
 
1270
1158
    def test_dir2_entry_to_bytes(self):
1271
1159
        inv = CHKInventory(None)
1272
 
        ie = inventory.InventoryDirectory(b'dir-id', u'dir\u03a9name',
 
1160
        ie = inventory.InventoryDirectory('dir-id', u'dir\u03a9name',
1273
1161
                                          None)
1274
 
        ie.revision = b'dir-rev-id'
 
1162
        ie.revision = 'dir-rev-id'
1275
1163
        bytes = inv._entry_to_bytes(ie)
1276
 
        self.assertEqual(b'dir: dir-id\n\ndir\xce\xa9name\n'
1277
 
                         b'dir-rev-id', bytes)
 
1164
        self.assertEqual('dir: dir-id\n\ndir\xce\xa9name\n'
 
1165
                         'dir-rev-id', bytes)
1278
1166
        ie2 = inv._bytes_to_entry(bytes)
1279
1167
        self.assertEqual(ie, ie2)
1280
 
        self.assertIsInstance(ie2.name, text_type)
 
1168
        self.assertIsInstance(ie2.name, unicode)
1281
1169
        self.assertIs(ie2.parent_id, None)
1282
 
        self.assertEqual((b'dir\xce\xa9name', b'dir-id', b'dir-rev-id'),
 
1170
        self.assertEqual(('dir\xce\xa9name', 'dir-id', 'dir-rev-id'),
1283
1171
                         inv._bytes_to_utf8name_key(bytes))
1284
1172
 
1285
1173
    def test_symlink_entry_to_bytes(self):
1286
1174
        inv = CHKInventory(None)
1287
 
        ie = inventory.InventoryLink(b'link-id', 'linkname', b'parent-id')
1288
 
        ie.revision = b'link-rev-id'
 
1175
        ie = inventory.InventoryLink('link-id', 'linkname', 'parent-id')
 
1176
        ie.revision = 'link-rev-id'
1289
1177
        ie.symlink_target = u'target/path'
1290
1178
        bytes = inv._entry_to_bytes(ie)
1291
 
        self.assertEqual(b'symlink: link-id\nparent-id\nlinkname\n'
1292
 
                         b'link-rev-id\ntarget/path', bytes)
 
1179
        self.assertEqual('symlink: link-id\nparent-id\nlinkname\n'
 
1180
                         'link-rev-id\ntarget/path', bytes)
1293
1181
        ie2 = inv._bytes_to_entry(bytes)
1294
1182
        self.assertEqual(ie, ie2)
1295
 
        self.assertIsInstance(ie2.name, text_type)
1296
 
        self.assertIsInstance(ie2.symlink_target, text_type)
1297
 
        self.assertEqual((b'linkname', b'link-id', b'link-rev-id'),
 
1183
        self.assertIsInstance(ie2.name, unicode)
 
1184
        self.assertIsInstance(ie2.symlink_target, unicode)
 
1185
        self.assertEqual(('linkname', 'link-id', 'link-rev-id'),
1298
1186
                         inv._bytes_to_utf8name_key(bytes))
1299
1187
 
1300
1188
    def test_symlink2_entry_to_bytes(self):
1301
1189
        inv = CHKInventory(None)
1302
 
        ie = inventory.InventoryLink(
1303
 
            b'link-id', u'link\u03a9name', b'parent-id')
1304
 
        ie.revision = b'link-rev-id'
 
1190
        ie = inventory.InventoryLink('link-id', u'link\u03a9name', 'parent-id')
 
1191
        ie.revision = 'link-rev-id'
1305
1192
        ie.symlink_target = u'target/\u03a9path'
1306
1193
        bytes = inv._entry_to_bytes(ie)
1307
 
        self.assertEqual(b'symlink: link-id\nparent-id\nlink\xce\xa9name\n'
1308
 
                         b'link-rev-id\ntarget/\xce\xa9path', bytes)
 
1194
        self.assertEqual('symlink: link-id\nparent-id\nlink\xce\xa9name\n'
 
1195
                         'link-rev-id\ntarget/\xce\xa9path', bytes)
1309
1196
        ie2 = inv._bytes_to_entry(bytes)
1310
1197
        self.assertEqual(ie, ie2)
1311
 
        self.assertIsInstance(ie2.name, text_type)
1312
 
        self.assertIsInstance(ie2.symlink_target, text_type)
1313
 
        self.assertEqual((b'link\xce\xa9name', b'link-id', b'link-rev-id'),
 
1198
        self.assertIsInstance(ie2.name, unicode)
 
1199
        self.assertIsInstance(ie2.symlink_target, unicode)
 
1200
        self.assertEqual(('link\xce\xa9name', 'link-id', 'link-rev-id'),
1314
1201
                         inv._bytes_to_utf8name_key(bytes))
1315
1202
 
1316
1203
    def test_tree_reference_entry_to_bytes(self):
1317
1204
        inv = CHKInventory(None)
1318
 
        ie = inventory.TreeReference(b'tree-root-id', u'tree\u03a9name',
1319
 
                                     b'parent-id')
1320
 
        ie.revision = b'tree-rev-id'
1321
 
        ie.reference_revision = b'ref-rev-id'
 
1205
        ie = inventory.TreeReference('tree-root-id', u'tree\u03a9name',
 
1206
                                     'parent-id')
 
1207
        ie.revision = 'tree-rev-id'
 
1208
        ie.reference_revision = 'ref-rev-id'
1322
1209
        bytes = inv._entry_to_bytes(ie)
1323
 
        self.assertEqual(b'tree: tree-root-id\nparent-id\ntree\xce\xa9name\n'
1324
 
                         b'tree-rev-id\nref-rev-id', bytes)
 
1210
        self.assertEqual('tree: tree-root-id\nparent-id\ntree\xce\xa9name\n'
 
1211
                         'tree-rev-id\nref-rev-id', bytes)
1325
1212
        ie2 = inv._bytes_to_entry(bytes)
1326
1213
        self.assertEqual(ie, ie2)
1327
 
        self.assertIsInstance(ie2.name, text_type)
1328
 
        self.assertEqual((b'tree\xce\xa9name', b'tree-root-id', b'tree-rev-id'),
 
1214
        self.assertIsInstance(ie2.name, unicode)
 
1215
        self.assertEqual(('tree\xce\xa9name', 'tree-root-id', 'tree-rev-id'),
1329
1216
                         inv._bytes_to_utf8name_key(bytes))
1330
1217
 
1331
 
    def make_basic_utf8_inventory(self):
1332
 
        inv = Inventory()
1333
 
        inv.revision_id = b"revid"
1334
 
        inv.root.revision = b"rootrev"
1335
 
        root_id = inv.root.file_id
1336
 
        inv.add(InventoryFile(b"fileid", u'f\xefle', root_id))
1337
 
        inv.get_entry(b"fileid").revision = b"filerev"
1338
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1339
 
        inv.get_entry(b"fileid").text_size = 0
1340
 
        inv.add(InventoryDirectory(b"dirid", u'dir-\N{EURO SIGN}', root_id))
1341
 
        inv.get_entry(b"dirid").revision = b"dirrev"
1342
 
        inv.add(InventoryFile(b"childid", u'ch\xefld', b"dirid"))
1343
 
        inv.get_entry(b"childid").revision = b"filerev"
1344
 
        inv.get_entry(b"childid").text_sha1 = b"ffff"
1345
 
        inv.get_entry(b"childid").text_size = 0
1346
 
        chk_bytes = self.get_chk_bytes()
1347
 
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1348
 
        lines = chk_inv.to_lines()
1349
 
        return CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
1350
 
 
1351
 
    def test__preload_handles_utf8(self):
1352
 
        new_inv = self.make_basic_utf8_inventory()
1353
 
        self.assertEqual({}, new_inv._fileid_to_entry_cache)
1354
 
        self.assertFalse(new_inv._fully_cached)
1355
 
        new_inv._preload_cache()
1356
 
        self.assertEqual(
1357
 
            sorted([new_inv.root_id, b"fileid", b"dirid", b"childid"]),
1358
 
            sorted(new_inv._fileid_to_entry_cache.keys()))
1359
 
        ie_root = new_inv._fileid_to_entry_cache[new_inv.root_id]
1360
 
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1361
 
                         sorted(ie_root._children.keys()))
1362
 
        ie_dir = new_inv._fileid_to_entry_cache[b'dirid']
1363
 
        self.assertEqual([u'ch\xefld'], sorted(ie_dir._children.keys()))
1364
 
 
1365
 
    def test__preload_populates_cache(self):
1366
 
        inv = Inventory()
1367
 
        inv.revision_id = b"revid"
1368
 
        inv.root.revision = b"rootrev"
1369
 
        root_id = inv.root.file_id
1370
 
        inv.add(InventoryFile(b"fileid", "file", root_id))
1371
 
        inv.get_entry(b"fileid").revision = b"filerev"
1372
 
        inv.get_entry(b"fileid").executable = True
1373
 
        inv.get_entry(b"fileid").text_sha1 = b"ffff"
1374
 
        inv.get_entry(b"fileid").text_size = 1
1375
 
        inv.add(InventoryDirectory(b"dirid", "dir", root_id))
1376
 
        inv.get_entry(b"dirid").revision = b"dirrev"
1377
 
        inv.add(InventoryFile(b"childid", "child", b"dirid"))
1378
 
        inv.get_entry(b"childid").revision = b"filerev"
1379
 
        inv.get_entry(b"childid").executable = False
1380
 
        inv.get_entry(b"childid").text_sha1 = b"dddd"
1381
 
        inv.get_entry(b"childid").text_size = 1
1382
 
        chk_bytes = self.get_chk_bytes()
1383
 
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv)
1384
 
        lines = chk_inv.to_lines()
1385
 
        new_inv = CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
1386
 
        self.assertEqual({}, new_inv._fileid_to_entry_cache)
1387
 
        self.assertFalse(new_inv._fully_cached)
1388
 
        new_inv._preload_cache()
1389
 
        self.assertEqual(
1390
 
            sorted([root_id, b"fileid", b"dirid", b"childid"]),
1391
 
            sorted(new_inv._fileid_to_entry_cache.keys()))
1392
 
        self.assertTrue(new_inv._fully_cached)
1393
 
        ie_root = new_inv._fileid_to_entry_cache[root_id]
1394
 
        self.assertEqual(['dir', 'file'], sorted(ie_root._children.keys()))
1395
 
        ie_dir = new_inv._fileid_to_entry_cache[b'dirid']
1396
 
        self.assertEqual(['child'], sorted(ie_dir._children.keys()))
1397
 
 
1398
 
    def test__preload_handles_partially_evaluated_inventory(self):
1399
 
        new_inv = self.make_basic_utf8_inventory()
1400
 
        ie = new_inv.get_entry(new_inv.root_id)
1401
 
        self.assertIs(None, ie._children)
1402
 
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1403
 
                         sorted(ie.children.keys()))
1404
 
        # Accessing .children loads _children
1405
 
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1406
 
                         sorted(ie._children.keys()))
1407
 
        new_inv._preload_cache()
1408
 
        # No change
1409
 
        self.assertEqual([u'dir-\N{EURO SIGN}', u'f\xefle'],
1410
 
                         sorted(ie._children.keys()))
1411
 
        ie_dir = new_inv.get_entry(b"dirid")
1412
 
        self.assertEqual([u'ch\xefld'],
1413
 
                         sorted(ie_dir._children.keys()))
1414
 
 
1415
 
    def test_filter_change_in_renamed_subfolder(self):
1416
 
        inv = Inventory(b'tree-root')
1417
 
        inv.root.revision = b'rootrev'
1418
 
        src_ie = inv.add_path('src', 'directory', b'src-id')
1419
 
        src_ie.revision = b'srcrev'
1420
 
        sub_ie = inv.add_path('src/sub/', 'directory', b'sub-id')
1421
 
        sub_ie.revision = b'subrev'
1422
 
        a_ie = inv.add_path('src/sub/a', 'file', b'a-id')
1423
 
        a_ie.revision = b'filerev'
1424
 
        a_ie.text_sha1 = osutils.sha_string(b'content\n')
1425
 
        a_ie.text_size = len(b'content\n')
1426
 
        chk_bytes = self.get_chk_bytes()
1427
 
        inv = CHKInventory.from_inventory(chk_bytes, inv)
1428
 
        inv = inv.create_by_apply_delta([
1429
 
            ("src/sub/a", "src/sub/a", b"a-id", a_ie),
1430
 
            ("src", "src2", b"src-id", src_ie),
1431
 
            ], b'new-rev-2')
1432
 
        new_inv = inv.filter([b'a-id', b'src-id'])
1433
 
        self.assertEqual([
1434
 
            ('', b'tree-root'),
1435
 
            ('src', b'src-id'),
1436
 
            ('src/sub', b'sub-id'),
1437
 
            ('src/sub/a', b'a-id'),
1438
 
            ], [(path, ie.file_id) for path, ie in new_inv.iter_entries()])
1439
 
 
1440
1218
 
1441
1219
class TestCHKInventoryExpand(tests.TestCaseWithMemoryTransport):
1442
1220
 
1445
1223
        trans = self.get_transport('')
1446
1224
        return factory(trans)
1447
1225
 
1448
 
    def make_dir(self, inv, name, parent_id, revision):
1449
 
        ie = inv.make_entry('directory', name, parent_id,
1450
 
                            name.encode('utf-8') + b'-id')
1451
 
        ie.revision = revision
1452
 
        inv.add(ie)
 
1226
    def make_dir(self, inv, name, parent_id):
 
1227
        inv.add(inv.make_entry('directory', name, parent_id, name + '-id'))
1453
1228
 
1454
 
    def make_file(self, inv, name, parent_id, revision, content=b'content\n'):
1455
 
        ie = inv.make_entry('file', name, parent_id,
1456
 
                            name.encode('utf-8') + b'-id')
 
1229
    def make_file(self, inv, name, parent_id, content='content\n'):
 
1230
        ie = inv.make_entry('file', name, parent_id, name + '-id')
1457
1231
        ie.text_sha1 = osutils.sha_string(content)
1458
1232
        ie.text_size = len(content)
1459
 
        ie.revision = revision
1460
1233
        inv.add(ie)
1461
1234
 
1462
1235
    def make_simple_inventory(self):
1463
 
        inv = Inventory(b'TREE_ROOT')
1464
 
        inv.revision_id = b"revid"
1465
 
        inv.root.revision = b"rootrev"
 
1236
        inv = Inventory('TREE_ROOT')
 
1237
        inv.revision_id = "revid"
 
1238
        inv.root.revision = "rootrev"
1466
1239
        # /                 TREE_ROOT
1467
1240
        # dir1/             dir1-id
1468
1241
        #   sub-file1       sub-file1-id
1472
1245
        # dir2/             dir2-id
1473
1246
        #   sub2-file1      sub2-file1-id
1474
1247
        # top               top-id
1475
 
        self.make_dir(inv, 'dir1', b'TREE_ROOT', b'dirrev')
1476
 
        self.make_dir(inv, 'dir2', b'TREE_ROOT', b'dirrev')
1477
 
        self.make_dir(inv, 'sub-dir1', b'dir1-id', b'dirrev')
1478
 
        self.make_file(inv, 'top', b'TREE_ROOT', b'filerev')
1479
 
        self.make_file(inv, 'sub-file1', b'dir1-id', b'filerev')
1480
 
        self.make_file(inv, 'sub-file2', b'dir1-id', b'filerev')
1481
 
        self.make_file(inv, 'subsub-file1', b'sub-dir1-id', b'filerev')
1482
 
        self.make_file(inv, 'sub2-file1', b'dir2-id', b'filerev')
 
1248
        self.make_dir(inv, 'dir1', 'TREE_ROOT')
 
1249
        self.make_dir(inv, 'dir2', 'TREE_ROOT')
 
1250
        self.make_dir(inv, 'sub-dir1', 'dir1-id')
 
1251
        self.make_file(inv, 'top', 'TREE_ROOT')
 
1252
        self.make_file(inv, 'sub-file1', 'dir1-id')
 
1253
        self.make_file(inv, 'sub-file2', 'dir1-id')
 
1254
        self.make_file(inv, 'subsub-file1', 'sub-dir1-id')
 
1255
        self.make_file(inv, 'sub2-file1', 'dir2-id')
1483
1256
        chk_bytes = self.get_chk_bytes()
1484
1257
        #  use a small maximum_size to force internal paging structures
1485
1258
        chk_inv = CHKInventory.from_inventory(chk_bytes, inv,
1486
 
                                              maximum_size=100,
1487
 
                                              search_key_name=b'hash-255-way')
1488
 
        lines = chk_inv.to_lines()
1489
 
        return CHKInventory.deserialise(chk_bytes, lines, (b"revid",))
 
1259
                        maximum_size=100,
 
1260
                        search_key_name='hash-255-way')
 
1261
        bytes = ''.join(chk_inv.to_lines())
 
1262
        return CHKInventory.deserialise(chk_bytes, bytes, ("revid",))
1490
1263
 
1491
1264
    def assert_Getitems(self, expected_fileids, inv, file_ids):
1492
1265
        self.assertEqual(sorted(expected_fileids),
1501
1274
        for entry in entries:
1502
1275
            s = expected_children.setdefault(entry.parent_id, [])
1503
1276
            s.append(entry.file_id)
1504
 
        val_children = {
1505
 
            k: sorted(v) for k, v in val_children.items()}
1506
 
        expected_children = {
1507
 
            k: sorted(v) for k, v in expected_children.items()}
 
1277
        val_children = dict((k, sorted(v)) for k, v
 
1278
                            in val_children.iteritems())
 
1279
        expected_children = dict((k, sorted(v)) for k, v
 
1280
                            in expected_children.iteritems())
1508
1281
        self.assertEqual(expected_children, val_children)
1509
1282
 
1510
1283
    def test_make_simple_inventory(self):
1513
1286
        for path, entry in inv.iter_entries_by_dir():
1514
1287
            layout.append((path, entry.file_id))
1515
1288
        self.assertEqual([
1516
 
            ('', b'TREE_ROOT'),
1517
 
            ('dir1', b'dir1-id'),
1518
 
            ('dir2', b'dir2-id'),
1519
 
            ('top', b'top-id'),
1520
 
            ('dir1/sub-dir1', b'sub-dir1-id'),
1521
 
            ('dir1/sub-file1', b'sub-file1-id'),
1522
 
            ('dir1/sub-file2', b'sub-file2-id'),
1523
 
            ('dir1/sub-dir1/subsub-file1', b'subsub-file1-id'),
1524
 
            ('dir2/sub2-file1', b'sub2-file1-id'),
 
1289
            ('', 'TREE_ROOT'),
 
1290
            ('dir1', 'dir1-id'),
 
1291
            ('dir2', 'dir2-id'),
 
1292
            ('top', 'top-id'),
 
1293
            ('dir1/sub-dir1', 'sub-dir1-id'),
 
1294
            ('dir1/sub-file1', 'sub-file1-id'),
 
1295
            ('dir1/sub-file2', 'sub-file2-id'),
 
1296
            ('dir1/sub-dir1/subsub-file1', 'subsub-file1-id'),
 
1297
            ('dir2/sub2-file1', 'sub2-file1-id'),
1525
1298
            ], layout)
1526
1299
 
1527
1300
    def test__getitems(self):
1528
1301
        inv = self.make_simple_inventory()
1529
1302
        # Reading from disk
1530
 
        self.assert_Getitems([b'dir1-id'], inv, [b'dir1-id'])
1531
 
        self.assertTrue(b'dir1-id' in inv._fileid_to_entry_cache)
1532
 
        self.assertFalse(b'sub-file2-id' in inv._fileid_to_entry_cache)
 
1303
        self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
 
1304
        self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
 
1305
        self.assertFalse('sub-file2-id' in inv._fileid_to_entry_cache)
1533
1306
        # From cache
1534
 
        self.assert_Getitems([b'dir1-id'], inv, [b'dir1-id'])
 
1307
        self.assert_Getitems(['dir1-id'], inv, ['dir1-id'])
1535
1308
        # Mixed
1536
 
        self.assert_Getitems([b'dir1-id', b'sub-file2-id'], inv,
1537
 
                             [b'dir1-id', b'sub-file2-id'])
1538
 
        self.assertTrue(b'dir1-id' in inv._fileid_to_entry_cache)
1539
 
        self.assertTrue(b'sub-file2-id' in inv._fileid_to_entry_cache)
 
1309
        self.assert_Getitems(['dir1-id', 'sub-file2-id'], inv,
 
1310
                             ['dir1-id', 'sub-file2-id'])
 
1311
        self.assertTrue('dir1-id' in inv._fileid_to_entry_cache)
 
1312
        self.assertTrue('sub-file2-id' in inv._fileid_to_entry_cache)
1540
1313
 
1541
1314
    def test_single_file(self):
1542
1315
        inv = self.make_simple_inventory()
1543
 
        self.assertExpand([b'TREE_ROOT', b'top-id'], inv, [b'top-id'])
 
1316
        self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
1544
1317
 
1545
1318
    def test_get_all_parents(self):
1546
1319
        inv = self.make_simple_inventory()
1547
 
        self.assertExpand([b'TREE_ROOT', b'dir1-id', b'sub-dir1-id',
1548
 
                           b'subsub-file1-id',
1549
 
                           ], inv, [b'subsub-file1-id'])
 
1320
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
 
1321
                           'subsub-file1-id',
 
1322
                          ], inv, ['subsub-file1-id'])
1550
1323
 
1551
1324
    def test_get_children(self):
1552
1325
        inv = self.make_simple_inventory()
1553
 
        self.assertExpand([b'TREE_ROOT', b'dir1-id', b'sub-dir1-id',
1554
 
                           b'sub-file1-id', b'sub-file2-id', b'subsub-file1-id',
1555
 
                           ], inv, [b'dir1-id'])
 
1326
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
 
1327
                           'sub-file1-id', 'sub-file2-id', 'subsub-file1-id',
 
1328
                          ], inv, ['dir1-id'])
1556
1329
 
1557
1330
    def test_from_root(self):
1558
1331
        inv = self.make_simple_inventory()
1559
 
        self.assertExpand([b'TREE_ROOT', b'dir1-id', b'dir2-id', b'sub-dir1-id',
1560
 
                           b'sub-file1-id', b'sub-file2-id', b'sub2-file1-id',
1561
 
                           b'subsub-file1-id', b'top-id'], inv, [b'TREE_ROOT'])
 
1332
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'dir2-id', 'sub-dir1-id',
 
1333
                           'sub-file1-id', 'sub-file2-id', 'sub2-file1-id',
 
1334
                           'subsub-file1-id', 'top-id'], inv, ['TREE_ROOT'])
1562
1335
 
1563
1336
    def test_top_level_file(self):
1564
1337
        inv = self.make_simple_inventory()
1565
 
        self.assertExpand([b'TREE_ROOT', b'top-id'], inv, [b'top-id'])
 
1338
        self.assertExpand(['TREE_ROOT', 'top-id'], inv, ['top-id'])
1566
1339
 
1567
1340
    def test_subsub_file(self):
1568
1341
        inv = self.make_simple_inventory()
1569
 
        self.assertExpand([b'TREE_ROOT', b'dir1-id', b'sub-dir1-id',
1570
 
                           b'subsub-file1-id'], inv, [b'subsub-file1-id'])
 
1342
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id',
 
1343
                           'subsub-file1-id'], inv, ['subsub-file1-id'])
1571
1344
 
1572
1345
    def test_sub_and_root(self):
1573
1346
        inv = self.make_simple_inventory()
1574
 
        self.assertExpand([b'TREE_ROOT', b'dir1-id', b'sub-dir1-id', b'top-id',
1575
 
                           b'subsub-file1-id'], inv, [b'top-id', b'subsub-file1-id'])
1576
 
 
1577
 
 
1578
 
class TestMutableInventoryFromTree(TestCaseWithTransport):
1579
 
 
1580
 
    def test_empty(self):
1581
 
        repository = self.make_repository('.')
1582
 
        tree = repository.revision_tree(revision.NULL_REVISION)
1583
 
        inv = mutable_inventory_from_tree(tree)
1584
 
        self.assertEqual(revision.NULL_REVISION, inv.revision_id)
1585
 
        self.assertEqual(0, len(inv))
1586
 
 
1587
 
    def test_some_files(self):
1588
 
        wt = self.make_branch_and_tree('.')
1589
 
        self.build_tree(['a'])
1590
 
        wt.add(['a'], [b'thefileid'])
1591
 
        revid = wt.commit("commit")
1592
 
        tree = wt.branch.repository.revision_tree(revid)
1593
 
        inv = mutable_inventory_from_tree(tree)
1594
 
        self.assertEqual(revid, inv.revision_id)
1595
 
        self.assertEqual(2, len(inv))
1596
 
        self.assertEqual("a", inv.get_entry(b'thefileid').name)
1597
 
        # The inventory should be mutable and independent of
1598
 
        # the original tree
1599
 
        self.assertFalse(tree.root_inventory.get_entry(
1600
 
            b'thefileid').executable)
1601
 
        inv.get_entry(b'thefileid').executable = True
1602
 
        self.assertFalse(tree.root_inventory.get_entry(
1603
 
            b'thefileid').executable)
 
1347
        self.assertExpand(['TREE_ROOT', 'dir1-id', 'sub-dir1-id', 'top-id',
 
1348
                           'subsub-file1-id'], inv, ['top-id', 'subsub-file1-id'])