/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005, 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
963 by Martin Pool
- add the start of a test for inventory file-id matching
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
963 by Martin Pool
- add the start of a test for inventory file-id matching
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
963 by Martin Pool
- add the start of a test for inventory file-id matching
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
17
from cStringIO import StringIO
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
18
import os
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
19
import time
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
20
1830.3.5 by John Arbash Meinel
make_entry refuses to create non-normalized entries.
21
from bzrlib import errors, inventory, osutils
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
22
from bzrlib.branch import Branch
23
from bzrlib.diff import internal_diff
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
24
from bzrlib.inventory import (Inventory, ROOT_ID, InventoryFile,
2100.3.1 by Aaron Bentley
Start roundtripping tree-reference entries
25
    InventoryDirectory, InventoryEntry, TreeReference)
1740.3.4 by Jelmer Vernooij
Move inventory to commit builder.
26
from bzrlib.osutils import (has_symlinks, rename, pathjoin, is_inside_any, 
27
    is_inside_or_parent_of_any)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
28
from bzrlib.tests import TestCase, TestCaseWithTransport
1551.2.54 by abentley
Fixed executability test
29
from bzrlib.transform import TreeTransform
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
30
from bzrlib.uncommit import uncommit
963 by Martin Pool
- add the start of a test for inventory file-id matching
31
969 by Martin Pool
- Add less-sucky is_within_any
32
1102 by Martin Pool
- merge test refactoring from robertc
33
class TestInventory(TestCase):
34
2178.2.2 by Jelmer Vernooij
Make add_path() return inventory entry for root just like it does for other entries.
35
    def test_add_path(self):
36
37
        inv = Inventory(root_id=None)
38
        self.assertIs(None, inv.root)
39
        ie = inv.add_path("", "directory", "my-root")
40
        self.assertEqual("my-root", ie.file_id)
41
        self.assertIs(ie, inv.root)
42
1102 by Martin Pool
- merge test refactoring from robertc
43
    def test_is_within(self):
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
44
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
45
        SRC_FOO_C = pathjoin('src', 'foo.c')
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
46
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
47
                         (['src'], SRC_FOO_C),
968 by Martin Pool
- add some passing tests for is_inside_any
48
                         (['src'], 'src'),
49
                         ]:
50
            self.assert_(is_inside_any(dirs, fn))
51
            
969 by Martin Pool
- Add less-sucky is_within_any
52
        for dirs, fn in [(['src'], 'srccontrol'),
53
                         (['src'], 'srccontrol/foo')]:
54
            self.assertFalse(is_inside_any(dirs, fn))
1740.3.4 by Jelmer Vernooij
Move inventory to commit builder.
55
56
    def test_is_within_or_parent(self):
57
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
58
                         (['src'], 'src/foo.c'),
59
                         (['src/bar.c'], 'src'),
60
                         (['src/bar.c', 'bla/foo.c'], 'src'),
61
                         (['src'], 'src'),
62
                         ]:
63
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
969 by Martin Pool
- Add less-sucky is_within_any
64
            
1740.3.4 by Jelmer Vernooij
Move inventory to commit builder.
65
        for dirs, fn in [(['src'], 'srccontrol'),
66
                         (['srccontrol/foo.c'], 'src'),
67
                         (['src'], 'srccontrol/foo')]:
68
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
69
1102 by Martin Pool
- merge test refactoring from robertc
70
    def test_ids(self):
963 by Martin Pool
- add the start of a test for inventory file-id matching
71
        """Test detection of files within selected directories."""
72
        inv = Inventory()
73
        
74
        for args in [('src', 'directory', 'src-id'), 
75
                     ('doc', 'directory', 'doc-id'), 
76
                     ('src/hello.c', 'file'),
77
                     ('src/bye.c', 'file', 'bye-id'),
78
                     ('Makefile', 'file')]:
79
            inv.add_path(*args)
80
            
81
        self.assertEqual(inv.path2id('src'), 'src-id')
82
        self.assertEqual(inv.path2id('src/bye.c'), 'bye-id')
83
        
84
        self.assert_('src-id' in inv)
1180 by Martin Pool
- start splitting code for xml (de)serialization away from objects
85
2091.3.1 by Aaron Bentley
When 'directory' path element isn't a directory, return None from path2id
86
    def test_non_directory_children(self):
87
        """Test path2id when a parent directory has no children"""
88
        inv = inventory.Inventory('tree_root')
89
        inv.add(inventory.InventoryFile('file-id','file', 
90
                                        parent_id='tree_root'))
91
        inv.add(inventory.InventoryLink('link-id','link', 
92
                                        parent_id='tree_root'))
93
        self.assertIs(None, inv.path2id('file/subfile'))
94
        self.assertIs(None, inv.path2id('link/subfile'))
95
1732.1.23 by John Arbash Meinel
Switch iter_entries from being a recursive function and using pathjoin
96
    def test_iter_entries(self):
97
        inv = Inventory()
98
        
99
        for args in [('src', 'directory', 'src-id'), 
100
                     ('doc', 'directory', 'doc-id'), 
101
                     ('src/hello.c', 'file', 'hello-id'),
102
                     ('src/bye.c', 'file', 'bye-id'),
103
                     ('Makefile', 'file', 'makefile-id')]:
104
            inv.add_path(*args)
105
106
        self.assertEqual([
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
107
            ('', ROOT_ID),
1732.1.23 by John Arbash Meinel
Switch iter_entries from being a recursive function and using pathjoin
108
            ('Makefile', 'makefile-id'),
109
            ('doc', 'doc-id'),
110
            ('src', 'src-id'),
111
            ('src/bye.c', 'bye-id'),
112
            ('src/hello.c', 'hello-id'),
113
            ], [(path, ie.file_id) for path, ie in inv.iter_entries()])
114
            
1711.2.36 by John Arbash Meinel
Add an iter_entries_by_dir which returns directory children before their children.
115
    def test_iter_entries_by_dir(self):
116
        inv = Inventory()
117
        
118
        for args in [('src', 'directory', 'src-id'), 
119
                     ('doc', 'directory', 'doc-id'), 
120
                     ('src/hello.c', 'file', 'hello-id'),
121
                     ('src/bye.c', 'file', 'bye-id'),
122
                     ('zz', 'file', 'zz-id'),
123
                     ('src/sub/', 'directory', 'sub-id'),
124
                     ('src/zz.c', 'file', 'zzc-id'),
125
                     ('src/sub/a', 'file', 'a-id'),
126
                     ('Makefile', 'file', 'makefile-id')]:
127
            inv.add_path(*args)
128
129
        self.assertEqual([
1852.6.6 by Robert Collins
Finish updating iter_entries change to make all tests pass.
130
            ('', ROOT_ID),
1711.2.36 by John Arbash Meinel
Add an iter_entries_by_dir which returns directory children before their children.
131
            ('Makefile', 'makefile-id'),
132
            ('doc', 'doc-id'),
133
            ('src', 'src-id'),
134
            ('zz', 'zz-id'),
135
            ('src/bye.c', 'bye-id'),
136
            ('src/hello.c', 'hello-id'),
137
            ('src/sub', 'sub-id'),
138
            ('src/zz.c', 'zzc-id'),
139
            ('src/sub/a', 'a-id'),
140
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
141
            
1551.9.29 by Aaron Bentley
Optimize Tree._iter_changes with specific file_ids
142
        self.assertEqual([
143
            ('', ROOT_ID),
144
            ('Makefile', 'makefile-id'),
145
            ('doc', 'doc-id'),
146
            ('src', 'src-id'),
147
            ('zz', 'zz-id'),
148
            ('src/bye.c', 'bye-id'),
149
            ('src/hello.c', 'hello-id'),
150
            ('src/sub', 'sub-id'),
151
            ('src/zz.c', 'zzc-id'),
152
            ('src/sub/a', 'a-id'),
153
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
154
                specific_file_ids=('a-id', 'zzc-id', 'doc-id', ROOT_ID,
155
                'hello-id', 'bye-id', 'zz-id', 'src-id', 'makefile-id', 
156
                'sub-id'))])
157
158
        self.assertEqual([
159
            ('Makefile', 'makefile-id'),
160
            ('doc', 'doc-id'),
161
            ('zz', 'zz-id'),
162
            ('src/bye.c', 'bye-id'),
163
            ('src/hello.c', 'hello-id'),
164
            ('src/zz.c', 'zzc-id'),
165
            ('src/sub/a', 'a-id'),
166
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
167
                specific_file_ids=('a-id', 'zzc-id', 'doc-id',
168
                'hello-id', 'bye-id', 'zz-id', 'makefile-id'))])
169
170
        self.assertEqual([
171
            ('Makefile', 'makefile-id'),
172
            ('src/bye.c', 'bye-id'),
173
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
174
                specific_file_ids=('bye-id', 'makefile-id'))])
175
176
        self.assertEqual([
177
            ('Makefile', 'makefile-id'),
178
            ('src/bye.c', 'bye-id'),
179
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
180
                specific_file_ids=('bye-id', 'makefile-id'))])
181
182
        self.assertEqual([
183
            ('src/bye.c', 'bye-id'),
184
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
185
                specific_file_ids=('bye-id',))])
186
1180 by Martin Pool
- start splitting code for xml (de)serialization away from objects
187
    def test_version(self):
188
        """Inventory remembers the text's version."""
189
        inv = Inventory()
190
        ie = inv.add_path('foo.txt', 'file')
191
        ## XXX
192
2100.3.6 by Aaron Bentley
Make add recursive for children of added entries
193
    def test_add_recursive(self):
194
        parent = InventoryDirectory('src-id', 'src', ROOT_ID)
195
        child = InventoryFile('hello-id', 'hello.c', 'src-id')
196
        parent.children[child.file_id] = child
197
        inv = Inventory()
198
        inv.add(parent)
199
        self.assertEqual('src/hello.c', inv.id2path('hello-id'))
200
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
201
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
202
class TestInventoryEntry(TestCase):
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
203
204
    def test_file_kind_character(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
205
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
206
        self.assertEqual(file.kind_character(), '')
207
208
    def test_dir_kind_character(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
209
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
210
        self.assertEqual(dir.kind_character(), '/')
211
212
    def test_link_kind_character(self):
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
213
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
214
        self.assertEqual(dir.kind_character(), '')
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
215
216
    def test_dir_detect_changes(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
217
        left = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
218
        left.text_sha1 = 123
219
        left.executable = True
220
        left.symlink_target='foo'
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
221
        right = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
222
        right.text_sha1 = 321
223
        right.symlink_target='bar'
224
        self.assertEqual((False, False), left.detect_changes(right))
225
        self.assertEqual((False, False), right.detect_changes(left))
226
227
    def test_file_detect_changes(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
228
        left = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
229
        left.text_sha1 = 123
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
230
        right = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
231
        right.text_sha1 = 123
232
        self.assertEqual((False, False), left.detect_changes(right))
233
        self.assertEqual((False, False), right.detect_changes(left))
234
        left.executable = True
235
        self.assertEqual((False, True), left.detect_changes(right))
236
        self.assertEqual((False, True), right.detect_changes(left))
237
        right.text_sha1 = 321
238
        self.assertEqual((True, True), left.detect_changes(right))
239
        self.assertEqual((True, True), right.detect_changes(left))
240
241
    def test_symlink_detect_changes(self):
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
242
        left = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
243
        left.text_sha1 = 123
244
        left.executable = True
245
        left.symlink_target='foo'
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
246
        right = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
247
        right.text_sha1 = 321
248
        right.symlink_target='foo'
249
        self.assertEqual((False, False), left.detect_changes(right))
250
        self.assertEqual((False, False), right.detect_changes(left))
251
        left.symlink_target = 'different'
252
        self.assertEqual((True, False), left.detect_changes(right))
253
        self.assertEqual((True, False), right.detect_changes(left))
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
254
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
255
    def test_file_has_text(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
256
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
257
        self.failUnless(file.has_text())
258
259
    def test_directory_has_text(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
260
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
261
        self.failIf(dir.has_text())
262
263
    def test_link_has_text(self):
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
264
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
265
        self.failIf(link.has_text())
266
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
267
    def test_make_entry(self):
268
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
269
            inventory.InventoryFile)
270
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
271
            inventory.InventoryLink)
272
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
273
            inventory.InventoryDirectory)
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
274
1830.3.5 by John Arbash Meinel
make_entry refuses to create non-normalized entries.
275
    def test_make_entry_non_normalized(self):
276
        orig_normalized_filename = osutils.normalized_filename
277
278
        try:
279
            osutils.normalized_filename = osutils._accessible_normalized_filename
280
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
281
            self.assertEqual(u'\xe5', entry.name)
282
            self.assertIsInstance(entry, inventory.InventoryFile)
283
284
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
285
            self.assertRaises(errors.InvalidNormalization,
286
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
287
        finally:
288
            osutils.normalized_filename = orig_normalized_filename
289
290
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
291
class TestEntryDiffing(TestCaseWithTransport):
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
292
293
    def setUp(self):
294
        super(TestEntryDiffing, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
295
        self.wt = self.make_branch_and_tree('.')
296
        self.branch = self.wt.branch
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
297
        print >> open('file', 'wb'), 'foo'
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
298
        print >> open('binfile', 'wb'), 'foo'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
299
        self.wt.add(['file'], ['fileid'])
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
300
        self.wt.add(['binfile'], ['binfileid'])
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
301
        if has_symlinks():
302
            os.symlink('target1', 'symlink')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
303
            self.wt.add(['symlink'], ['linkid'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
304
        self.wt.commit('message_1', rev_id = '1')
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
305
        print >> open('file', 'wb'), 'bar'
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
306
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
307
        if has_symlinks():
308
            os.unlink('symlink')
309
            os.symlink('target2', 'symlink')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
310
        self.tree_1 = self.branch.repository.revision_tree('1')
311
        self.inv_1 = self.branch.repository.get_inventory('1')
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
312
        self.file_1 = self.inv_1['fileid']
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
313
        self.file_1b = self.inv_1['binfileid']
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
314
        self.tree_2 = self.wt
2255.7.67 by Robert Collins
Fix test_inv - make setting WorkingTree4._dirty use a helper to reduce code duplication, and reset the inventory when we dont manually update it, if it exists.
315
        self.tree_2.lock_read()
316
        self.addCleanup(self.tree_2.unlock)
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
317
        self.inv_2 = self.tree_2.read_working_inventory()
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
318
        self.file_2 = self.inv_2['fileid']
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
319
        self.file_2b = self.inv_2['binfileid']
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
320
        if has_symlinks():
321
            self.link_1 = self.inv_1['linkid']
322
            self.link_2 = self.inv_2['linkid']
323
324
    def test_file_diff_deleted(self):
325
        output = StringIO()
326
        self.file_1.diff(internal_diff, 
327
                          "old_label", self.tree_1,
328
                          "/dev/null", None, None,
329
                          output)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
330
        self.assertEqual(output.getvalue(), "--- old_label\n"
331
                                            "+++ /dev/null\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
332
                                            "@@ -1,1 +0,0 @@\n"
333
                                            "-foo\n"
334
                                            "\n")
335
336
    def test_file_diff_added(self):
337
        output = StringIO()
338
        self.file_1.diff(internal_diff, 
339
                          "new_label", self.tree_1,
340
                          "/dev/null", None, None,
341
                          output, reverse=True)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
342
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
343
                                            "+++ new_label\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
344
                                            "@@ -0,0 +1,1 @@\n"
345
                                            "+foo\n"
346
                                            "\n")
347
348
    def test_file_diff_changed(self):
349
        output = StringIO()
350
        self.file_1.diff(internal_diff, 
351
                          "/dev/null", self.tree_1, 
352
                          "new_label", self.file_2, self.tree_2,
353
                          output)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
354
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
355
                                            "+++ new_label\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
356
                                            "@@ -1,1 +1,1 @@\n"
357
                                            "-foo\n"
358
                                            "+bar\n"
359
                                            "\n")
360
        
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
361
    def test_file_diff_binary(self):
362
        output = StringIO()
363
        self.file_1.diff(internal_diff, 
364
                          "/dev/null", self.tree_1, 
365
                          "new_label", self.file_2b, self.tree_2,
366
                          output)
1558.15.11 by Aaron Bentley
Apply merge review suggestions
367
        self.assertEqual(output.getvalue(), 
368
                         "Binary files /dev/null and new_label differ\n")
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
369
    def test_link_diff_deleted(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
370
        if not has_symlinks():
371
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
372
        output = StringIO()
373
        self.link_1.diff(internal_diff, 
374
                          "old_label", self.tree_1,
375
                          "/dev/null", None, None,
376
                          output)
377
        self.assertEqual(output.getvalue(),
378
                         "=== target was 'target1'\n")
379
380
    def test_link_diff_added(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
381
        if not has_symlinks():
382
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
383
        output = StringIO()
384
        self.link_1.diff(internal_diff, 
385
                          "new_label", self.tree_1,
386
                          "/dev/null", None, None,
387
                          output, reverse=True)
388
        self.assertEqual(output.getvalue(),
389
                         "=== target is 'target1'\n")
390
391
    def test_link_diff_changed(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
392
        if not has_symlinks():
393
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
394
        output = StringIO()
395
        self.link_1.diff(internal_diff, 
396
                          "/dev/null", self.tree_1, 
397
                          "new_label", self.link_2, self.tree_2,
398
                          output)
399
        self.assertEqual(output.getvalue(),
400
                         "=== target changed 'target1' => 'target2'\n")
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
401
402
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
403
class TestSnapshot(TestCaseWithTransport):
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
404
405
    def setUp(self):
406
        # for full testing we'll need a branch
407
        # with a subdir to test parent changes.
408
        # and a file, link and dir under that.
409
        # but right now I only need one attribute
410
        # to change, and then test merge patterns
411
        # with fake parent entries.
412
        super(TestSnapshot, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
413
        self.wt = self.make_branch_and_tree('.')
414
        self.branch = self.wt.branch
1185.38.7 by John Arbash Meinel
Updated build_tree to use fixed line-endings for tests which read the file contents and compare
415
        self.build_tree(['subdir/', 'subdir/file'], line_endings='binary')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
416
        self.wt.add(['subdir', 'subdir/file'],
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
417
                                       ['dirid', 'fileid'])
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
418
        if has_symlinks():
419
            pass
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
420
        self.wt.commit('message_1', rev_id = '1')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
421
        self.tree_1 = self.branch.repository.revision_tree('1')
422
        self.inv_1 = self.branch.repository.get_inventory('1')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
423
        self.file_1 = self.inv_1['fileid']
2255.7.54 by Robert Collins
in test_inv, stop abusing the inventory interface to get tree alterations to occur.
424
        self.wt.lock_write()
425
        self.addCleanup(self.wt.unlock)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
426
        self.file_active = self.wt.inventory['fileid']
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
427
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
428
429
    def test_snapshot_new_revision(self):
430
        # This tests that a simple commit with no parents makes a new
431
        # revision value in the inventory entry
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
432
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
433
        # expected outcome - file_1 has a revision id of '2', and we can get
434
        # its text of 'file contents' out of the weave.
435
        self.assertEqual(self.file_1.revision, '1')
436
        self.assertEqual(self.file_active.revision, '2')
437
        # this should be a separate test probably, but lets check it once..
1563.2.30 by Robert Collins
Remove all but fetch references to revision_store, making the repository references that are weave specific use the RevisionTextStore.text_store attribute.
438
        lines = self.branch.repository.weave_store.get_weave(
439
            'fileid', 
440
            self.branch.get_transaction()).get_lines('2')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
441
        self.assertEqual(lines, ['contents of subdir/file\n'])
442
443
    def test_snapshot_unchanged(self):
444
        #This tests that a simple commit does not make a new entry for
445
        # an unchanged inventory entry
446
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
447
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
448
        self.assertEqual(self.file_1.revision, '1')
449
        self.assertEqual(self.file_active.revision, '1')
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
450
        vf = self.branch.repository.weave_store.get_weave(
451
            'fileid', 
452
            self.branch.repository.get_transaction())
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
453
        self.assertRaises(errors.RevisionNotPresent,
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
454
                          vf.get_lines,
455
                          '2')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
456
457
    def test_snapshot_merge_identical_different_revid(self):
458
        # This tests that a commit with two identical parents, one of which has
459
        # a different revision id, results in a new revision id in the entry.
1408 by Robert Collins
we do not need revision_trees in commit, parent inventories are sufficient
460
        # 1->other, commit a merge of other against 1, results in 2.
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
461
        other_ie = inventory.InventoryFile('fileid', 'newname', self.file_1.parent_id)
462
        other_ie = inventory.InventoryFile('fileid', 'file', self.file_1.parent_id)
463
        other_ie.revision = '1'
464
        other_ie.text_sha1 = self.file_1.text_sha1
465
        other_ie.text_size = self.file_1.text_size
466
        self.assertEqual(self.file_1, other_ie)
467
        other_ie.revision = 'other'
468
        self.assertNotEqual(self.file_1, other_ie)
1563.2.10 by Robert Collins
Change weave store to be a versioned store, using WeaveFiles which maintain integrity without needing explicit 'put' operations.
469
        versionfile = self.branch.repository.weave_store.get_weave(
470
            'fileid', self.branch.repository.get_transaction())
471
        versionfile.clone_text('other', '1', ['1'])
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
472
        self.file_active.snapshot('2', 'subdir/file', 
473
                                  {'1':self.file_1, 'other':other_ie},
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
474
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
475
        self.assertEqual(self.file_active.revision, '2')
476
477
    def test_snapshot_changed(self):
478
        # This tests that a commit with one different parent results in a new
479
        # revision id in the entry.
2255.7.54 by Robert Collins
in test_inv, stop abusing the inventory interface to get tree alterations to occur.
480
        self.wt.rename_one('subdir/file', 'subdir/newname')
481
        self.file_active = self.wt.inventory['fileid']
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
482
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
483
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
484
        # expected outcome - file_1 has a revision id of '2'
485
        self.assertEqual(self.file_active.revision, '2')
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
486
487
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
488
class TestPreviousHeads(TestCaseWithTransport):
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
489
490
    def setUp(self):
491
        # we want several inventories, that respectively
492
        # give use the following scenarios:
493
        # A) fileid not in any inventory (A),
494
        # B) fileid present in one inventory (B) and (A,B)
495
        # C) fileid present in two inventories, and they
496
        #   are not mutual descendents (B, C)
497
        # D) fileid present in two inventories and one is
498
        #   a descendent of the other. (B, D)
499
        super(TestPreviousHeads, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
500
        self.wt = self.make_branch_and_tree('.')
501
        self.branch = self.wt.branch
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
502
        self.build_tree(['file'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
503
        self.wt.commit('new branch', allow_pointless=True, rev_id='A')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
504
        self.inv_A = self.branch.repository.get_inventory('A')
1185.65.13 by Robert Collins
Merge from integration
505
        self.wt.add(['file'], ['fileid'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
506
        self.wt.commit('add file', rev_id='B')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
507
        self.inv_B = self.branch.repository.get_inventory('B')
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
508
        uncommit(self.branch, tree=self.wt)
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
509
        self.assertEqual(self.branch.revision_history(), ['A'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
510
        self.wt.commit('another add of file', rev_id='C')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
511
        self.inv_C = self.branch.repository.get_inventory('C')
1908.6.7 by Robert Collins
Remove all users of set_pending_merges and add_pending_merge except tests that they work correctly.
512
        self.wt.add_parent_tree_id('B')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
513
        self.wt.commit('merge in B', rev_id='D')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
514
        self.inv_D = self.branch.repository.get_inventory('D')
2255.7.67 by Robert Collins
Fix test_inv - make setting WorkingTree4._dirty use a helper to reduce code duplication, and reset the inventory when we dont manually update it, if it exists.
515
        self.wt.lock_read()
516
        self.addCleanup(self.wt.unlock)
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
517
        self.file_active = self.wt.inventory['fileid']
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
518
        self.weave = self.branch.repository.weave_store.get_weave('fileid',
1596.2.20 by Robert Collins
optimise commit to only access weaves for merged, or altered files during commit.
519
            self.branch.repository.get_transaction())
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
520
        
521
    def get_previous_heads(self, inventories):
1596.2.20 by Robert Collins
optimise commit to only access weaves for merged, or altered files during commit.
522
        return self.file_active.find_previous_heads(
523
            inventories, 
524
            self.branch.repository.weave_store,
525
            self.branch.repository.get_transaction())
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
526
        
527
    def test_fileid_in_no_inventory(self):
528
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
529
530
    def test_fileid_in_one_inventory(self):
531
        self.assertEqual({'B':self.inv_B['fileid']},
532
                         self.get_previous_heads([self.inv_B]))
533
        self.assertEqual({'B':self.inv_B['fileid']},
534
                         self.get_previous_heads([self.inv_A, self.inv_B]))
535
        self.assertEqual({'B':self.inv_B['fileid']},
536
                         self.get_previous_heads([self.inv_B, self.inv_A]))
537
538
    def test_fileid_in_two_inventories_gives_both_entries(self):
539
        self.assertEqual({'B':self.inv_B['fileid'],
540
                          'C':self.inv_C['fileid']},
541
                          self.get_previous_heads([self.inv_B, self.inv_C]))
542
        self.assertEqual({'B':self.inv_B['fileid'],
543
                          'C':self.inv_C['fileid']},
544
                          self.get_previous_heads([self.inv_C, self.inv_B]))
545
546
    def test_fileid_in_two_inventories_already_merged_gives_head(self):
547
        self.assertEqual({'D':self.inv_D['fileid']},
548
                         self.get_previous_heads([self.inv_B, self.inv_D]))
549
        self.assertEqual({'D':self.inv_D['fileid']},
550
                         self.get_previous_heads([self.inv_D, self.inv_B]))
551
552
    # TODO: test two inventories with the same file revision 
1185.31.55 by John Arbash Meinel
Added (win32 failing) test to make sure is_executable is maintained over several operations
553
554
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
555
class TestDescribeChanges(TestCase):
556
557
    def test_describe_change(self):
558
        # we need to test the following change combinations:
559
        # rename
560
        # reparent
561
        # modify
562
        # gone
563
        # added
564
        # renamed/reparented and modified
565
        # change kind (perhaps can't be done yet?)
566
        # also, merged in combination with all of these?
567
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
568
        old_a.text_sha1 = '123132'
569
        old_a.text_size = 0
570
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
571
        new_a.text_sha1 = '123132'
572
        new_a.text_size = 0
573
574
        self.assertChangeDescription('unchanged', old_a, new_a)
575
576
        new_a.text_size = 10
577
        new_a.text_sha1 = 'abcabc'
578
        self.assertChangeDescription('modified', old_a, new_a)
579
580
        self.assertChangeDescription('added', None, new_a)
581
        self.assertChangeDescription('removed', old_a, None)
582
        # perhaps a bit questionable but seems like the most reasonable thing...
583
        self.assertChangeDescription('unchanged', None, None)
584
585
        # in this case it's both renamed and modified; show a rename and 
586
        # modification:
587
        new_a.name = 'newfilename'
588
        self.assertChangeDescription('modified and renamed', old_a, new_a)
589
590
        # reparenting is 'renaming'
591
        new_a.name = old_a.name
592
        new_a.parent_id = 'somedir-id'
593
        self.assertChangeDescription('modified and renamed', old_a, new_a)
594
595
        # reset the content values so its not modified
596
        new_a.text_size = old_a.text_size
597
        new_a.text_sha1 = old_a.text_sha1
598
        new_a.name = old_a.name
599
600
        new_a.name = 'newfilename'
601
        self.assertChangeDescription('renamed', old_a, new_a)
602
603
        # reparenting is 'renaming'
604
        new_a.name = old_a.name
605
        new_a.parent_id = 'somedir-id'
606
        self.assertChangeDescription('renamed', old_a, new_a)
607
608
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
609
        change = InventoryEntry.describe_change(old_ie, new_ie)
610
        self.assertEqual(expected_change, change)
611
612
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
613
class TestRevert(TestCaseWithTransport):
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
614
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
615
    def test_dangling_id(self):
616
        wt = self.make_branch_and_tree('b1')
2255.7.67 by Robert Collins
Fix test_inv - make setting WorkingTree4._dirty use a helper to reduce code duplication, and reset the inventory when we dont manually update it, if it exists.
617
        wt.lock_tree_write()
618
        self.addCleanup(wt.unlock)
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
619
        self.assertEqual(len(wt.inventory), 1)
620
        open('b1/a', 'wb').write('a test\n')
621
        wt.add('a')
622
        self.assertEqual(len(wt.inventory), 2)
2255.7.67 by Robert Collins
Fix test_inv - make setting WorkingTree4._dirty use a helper to reduce code duplication, and reset the inventory when we dont manually update it, if it exists.
623
        wt.flush() # workaround revert doing wt._write_inventory for now.
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
624
        os.unlink('b1/a')
625
        wt.revert([])
626
        self.assertEqual(len(wt.inventory), 1)
1731.1.39 by Aaron Bentley
Reject removing is_root
627
628
629
class TestIsRoot(TestCase):
630
    """Ensure our root-checking code is accurate."""
631
632
    def test_is_root(self):
633
        inv = Inventory('TREE_ROOT')
634
        self.assertTrue(inv.is_root('TREE_ROOT'))
635
        self.assertFalse(inv.is_root('booga'))
636
        inv.root.file_id = 'booga'
637
        self.assertFalse(inv.is_root('TREE_ROOT'))
638
        self.assertTrue(inv.is_root('booga'))
639
        # works properly even if no root is set
640
        inv.root = None
641
        self.assertFalse(inv.is_root('TREE_ROOT'))
642
        self.assertFalse(inv.is_root('booga'))
2100.3.1 by Aaron Bentley
Start roundtripping tree-reference entries
643
644
645
class TestTreeReference(TestCase):
646
    
647
    def test_create(self):
648
        inv = Inventory('tree-root-123')
649
        inv.add(TreeReference('nested-id', 'nested', parent_id='tree-root-123',
650
                              revision='rev', reference_revision='rev2'))