/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,
25
    InventoryDirectory, InventoryEntry)
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
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
193
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
194
class TestInventoryEntry(TestCase):
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
195
196
    def test_file_kind_character(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
197
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
198
        self.assertEqual(file.kind_character(), '')
199
200
    def test_dir_kind_character(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
201
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
202
        self.assertEqual(dir.kind_character(), '/')
203
204
    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
205
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
206
        self.assertEqual(dir.kind_character(), '')
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
207
208
    def test_dir_detect_changes(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
209
        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
210
        left.text_sha1 = 123
211
        left.executable = True
212
        left.symlink_target='foo'
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
213
        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
214
        right.text_sha1 = 321
215
        right.symlink_target='bar'
216
        self.assertEqual((False, False), left.detect_changes(right))
217
        self.assertEqual((False, False), right.detect_changes(left))
218
219
    def test_file_detect_changes(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
220
        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
221
        left.text_sha1 = 123
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
222
        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
223
        right.text_sha1 = 123
224
        self.assertEqual((False, False), left.detect_changes(right))
225
        self.assertEqual((False, False), right.detect_changes(left))
226
        left.executable = True
227
        self.assertEqual((False, True), left.detect_changes(right))
228
        self.assertEqual((False, True), right.detect_changes(left))
229
        right.text_sha1 = 321
230
        self.assertEqual((True, True), left.detect_changes(right))
231
        self.assertEqual((True, True), right.detect_changes(left))
232
233
    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
234
        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
235
        left.text_sha1 = 123
236
        left.executable = True
237
        left.symlink_target='foo'
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
238
        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
239
        right.text_sha1 = 321
240
        right.symlink_target='foo'
241
        self.assertEqual((False, False), left.detect_changes(right))
242
        self.assertEqual((False, False), right.detect_changes(left))
243
        left.symlink_target = 'different'
244
        self.assertEqual((True, False), left.detect_changes(right))
245
        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
246
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
247
    def test_file_has_text(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
248
        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
249
        self.failUnless(file.has_text())
250
251
    def test_directory_has_text(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
252
        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
253
        self.failIf(dir.has_text())
254
255
    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
256
        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
257
        self.failIf(link.has_text())
258
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)
259
    def test_make_entry(self):
260
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
261
            inventory.InventoryFile)
262
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
263
            inventory.InventoryLink)
264
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
265
            inventory.InventoryDirectory)
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
266
1830.3.5 by John Arbash Meinel
make_entry refuses to create non-normalized entries.
267
    def test_make_entry_non_normalized(self):
268
        orig_normalized_filename = osutils.normalized_filename
269
270
        try:
271
            osutils.normalized_filename = osutils._accessible_normalized_filename
272
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
273
            self.assertEqual(u'\xe5', entry.name)
274
            self.assertIsInstance(entry, inventory.InventoryFile)
275
276
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
277
            self.assertRaises(errors.InvalidNormalization,
278
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
279
        finally:
280
            osutils.normalized_filename = orig_normalized_filename
281
282
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
283
class TestEntryDiffing(TestCaseWithTransport):
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
284
285
    def setUp(self):
286
        super(TestEntryDiffing, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
287
        self.wt = self.make_branch_and_tree('.')
288
        self.branch = self.wt.branch
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
289
        print >> open('file', 'wb'), 'foo'
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
290
        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.
291
        self.wt.add(['file'], ['fileid'])
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
292
        self.wt.add(['binfile'], ['binfileid'])
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
293
        if has_symlinks():
294
            os.symlink('target1', 'symlink')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
295
            self.wt.add(['symlink'], ['linkid'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
296
        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
297
        print >> open('file', 'wb'), 'bar'
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
298
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
299
        if has_symlinks():
300
            os.unlink('symlink')
301
            os.symlink('target2', 'symlink')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
302
        self.tree_1 = self.branch.repository.revision_tree('1')
303
        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
304
        self.file_1 = self.inv_1['fileid']
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
305
        self.file_1b = self.inv_1['binfileid']
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
306
        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.
307
        self.tree_2.lock_read()
308
        self.addCleanup(self.tree_2.unlock)
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
309
        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
310
        self.file_2 = self.inv_2['fileid']
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
311
        self.file_2b = self.inv_2['binfileid']
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
312
        if has_symlinks():
313
            self.link_1 = self.inv_1['linkid']
314
            self.link_2 = self.inv_2['linkid']
315
316
    def test_file_diff_deleted(self):
317
        output = StringIO()
318
        self.file_1.diff(internal_diff, 
319
                          "old_label", self.tree_1,
320
                          "/dev/null", None, None,
321
                          output)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
322
        self.assertEqual(output.getvalue(), "--- old_label\n"
323
                                            "+++ /dev/null\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
324
                                            "@@ -1,1 +0,0 @@\n"
325
                                            "-foo\n"
326
                                            "\n")
327
328
    def test_file_diff_added(self):
329
        output = StringIO()
330
        self.file_1.diff(internal_diff, 
331
                          "new_label", self.tree_1,
332
                          "/dev/null", None, None,
333
                          output, reverse=True)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
334
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
335
                                            "+++ new_label\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
336
                                            "@@ -0,0 +1,1 @@\n"
337
                                            "+foo\n"
338
                                            "\n")
339
340
    def test_file_diff_changed(self):
341
        output = StringIO()
342
        self.file_1.diff(internal_diff, 
343
                          "/dev/null", self.tree_1, 
344
                          "new_label", self.file_2, self.tree_2,
345
                          output)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
346
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
347
                                            "+++ new_label\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
348
                                            "@@ -1,1 +1,1 @@\n"
349
                                            "-foo\n"
350
                                            "+bar\n"
351
                                            "\n")
352
        
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
353
    def test_file_diff_binary(self):
354
        output = StringIO()
355
        self.file_1.diff(internal_diff, 
356
                          "/dev/null", self.tree_1, 
357
                          "new_label", self.file_2b, self.tree_2,
358
                          output)
1558.15.11 by Aaron Bentley
Apply merge review suggestions
359
        self.assertEqual(output.getvalue(), 
360
                         "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
361
    def test_link_diff_deleted(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
362
        if not has_symlinks():
363
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
364
        output = StringIO()
365
        self.link_1.diff(internal_diff, 
366
                          "old_label", self.tree_1,
367
                          "/dev/null", None, None,
368
                          output)
369
        self.assertEqual(output.getvalue(),
370
                         "=== target was 'target1'\n")
371
372
    def test_link_diff_added(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
373
        if not has_symlinks():
374
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
375
        output = StringIO()
376
        self.link_1.diff(internal_diff, 
377
                          "new_label", self.tree_1,
378
                          "/dev/null", None, None,
379
                          output, reverse=True)
380
        self.assertEqual(output.getvalue(),
381
                         "=== target is 'target1'\n")
382
383
    def test_link_diff_changed(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
384
        if not has_symlinks():
385
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
386
        output = StringIO()
387
        self.link_1.diff(internal_diff, 
388
                          "/dev/null", self.tree_1, 
389
                          "new_label", self.link_2, self.tree_2,
390
                          output)
391
        self.assertEqual(output.getvalue(),
392
                         "=== target changed 'target1' => 'target2'\n")
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
393
394
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
395
class TestSnapshot(TestCaseWithTransport):
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
396
397
    def setUp(self):
398
        # for full testing we'll need a branch
399
        # with a subdir to test parent changes.
400
        # and a file, link and dir under that.
401
        # but right now I only need one attribute
402
        # to change, and then test merge patterns
403
        # with fake parent entries.
404
        super(TestSnapshot, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
405
        self.wt = self.make_branch_and_tree('.')
406
        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
407
        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.
408
        self.wt.add(['subdir', 'subdir/file'],
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
409
                                       ['dirid', 'fileid'])
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
410
        if has_symlinks():
411
            pass
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
412
        self.wt.commit('message_1', rev_id = '1')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
413
        self.tree_1 = self.branch.repository.revision_tree('1')
414
        self.inv_1 = self.branch.repository.get_inventory('1')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
415
        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.
416
        self.wt.lock_write()
417
        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.
418
        self.file_active = self.wt.inventory['fileid']
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
419
        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
420
421
    def test_snapshot_new_revision(self):
422
        # This tests that a simple commit with no parents makes a new
423
        # revision value in the inventory entry
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
424
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
425
        # expected outcome - file_1 has a revision id of '2', and we can get
426
        # its text of 'file contents' out of the weave.
427
        self.assertEqual(self.file_1.revision, '1')
428
        self.assertEqual(self.file_active.revision, '2')
429
        # 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.
430
        lines = self.branch.repository.weave_store.get_weave(
431
            'fileid', 
432
            self.branch.get_transaction()).get_lines('2')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
433
        self.assertEqual(lines, ['contents of subdir/file\n'])
434
435
    def test_snapshot_unchanged(self):
436
        #This tests that a simple commit does not make a new entry for
437
        # an unchanged inventory entry
438
        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.
439
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
440
        self.assertEqual(self.file_1.revision, '1')
441
        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.
442
        vf = self.branch.repository.weave_store.get_weave(
443
            'fileid', 
444
            self.branch.repository.get_transaction())
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
445
        self.assertRaises(errors.RevisionNotPresent,
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
446
                          vf.get_lines,
447
                          '2')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
448
449
    def test_snapshot_merge_identical_different_revid(self):
450
        # This tests that a commit with two identical parents, one of which has
451
        # 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
452
        # 1->other, commit a merge of other against 1, results in 2.
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
453
        other_ie = inventory.InventoryFile('fileid', 'newname', self.file_1.parent_id)
454
        other_ie = inventory.InventoryFile('fileid', 'file', self.file_1.parent_id)
455
        other_ie.revision = '1'
456
        other_ie.text_sha1 = self.file_1.text_sha1
457
        other_ie.text_size = self.file_1.text_size
458
        self.assertEqual(self.file_1, other_ie)
459
        other_ie.revision = 'other'
460
        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.
461
        versionfile = self.branch.repository.weave_store.get_weave(
462
            'fileid', self.branch.repository.get_transaction())
463
        versionfile.clone_text('other', '1', ['1'])
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
464
        self.file_active.snapshot('2', 'subdir/file', 
465
                                  {'1':self.file_1, 'other':other_ie},
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
466
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
467
        self.assertEqual(self.file_active.revision, '2')
468
469
    def test_snapshot_changed(self):
470
        # This tests that a commit with one different parent results in a new
471
        # 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.
472
        self.wt.rename_one('subdir/file', 'subdir/newname')
473
        self.file_active = self.wt.inventory['fileid']
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
474
        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.
475
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
476
        # expected outcome - file_1 has a revision id of '2'
477
        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.
478
479
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
480
class TestPreviousHeads(TestCaseWithTransport):
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
481
482
    def setUp(self):
483
        # we want several inventories, that respectively
484
        # give use the following scenarios:
485
        # A) fileid not in any inventory (A),
486
        # B) fileid present in one inventory (B) and (A,B)
487
        # C) fileid present in two inventories, and they
488
        #   are not mutual descendents (B, C)
489
        # D) fileid present in two inventories and one is
490
        #   a descendent of the other. (B, D)
491
        super(TestPreviousHeads, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
492
        self.wt = self.make_branch_and_tree('.')
493
        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.
494
        self.build_tree(['file'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
495
        self.wt.commit('new branch', allow_pointless=True, rev_id='A')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
496
        self.inv_A = self.branch.repository.get_inventory('A')
1185.65.13 by Robert Collins
Merge from integration
497
        self.wt.add(['file'], ['fileid'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
498
        self.wt.commit('add file', rev_id='B')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
499
        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
500
        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.
501
        self.assertEqual(self.branch.revision_history(), ['A'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
502
        self.wt.commit('another add of file', rev_id='C')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
503
        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.
504
        self.wt.add_parent_tree_id('B')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
505
        self.wt.commit('merge in B', rev_id='D')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
506
        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.
507
        self.wt.lock_read()
508
        self.addCleanup(self.wt.unlock)
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
509
        self.file_active = self.wt.inventory['fileid']
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
510
        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.
511
            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.
512
        
513
    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.
514
        return self.file_active.find_previous_heads(
515
            inventories, 
516
            self.branch.repository.weave_store,
517
            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.
518
        
519
    def test_fileid_in_no_inventory(self):
520
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
521
522
    def test_fileid_in_one_inventory(self):
523
        self.assertEqual({'B':self.inv_B['fileid']},
524
                         self.get_previous_heads([self.inv_B]))
525
        self.assertEqual({'B':self.inv_B['fileid']},
526
                         self.get_previous_heads([self.inv_A, self.inv_B]))
527
        self.assertEqual({'B':self.inv_B['fileid']},
528
                         self.get_previous_heads([self.inv_B, self.inv_A]))
529
530
    def test_fileid_in_two_inventories_gives_both_entries(self):
531
        self.assertEqual({'B':self.inv_B['fileid'],
532
                          'C':self.inv_C['fileid']},
533
                          self.get_previous_heads([self.inv_B, self.inv_C]))
534
        self.assertEqual({'B':self.inv_B['fileid'],
535
                          'C':self.inv_C['fileid']},
536
                          self.get_previous_heads([self.inv_C, self.inv_B]))
537
538
    def test_fileid_in_two_inventories_already_merged_gives_head(self):
539
        self.assertEqual({'D':self.inv_D['fileid']},
540
                         self.get_previous_heads([self.inv_B, self.inv_D]))
541
        self.assertEqual({'D':self.inv_D['fileid']},
542
                         self.get_previous_heads([self.inv_D, self.inv_B]))
543
544
    # 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
545
546
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
547
class TestDescribeChanges(TestCase):
548
549
    def test_describe_change(self):
550
        # we need to test the following change combinations:
551
        # rename
552
        # reparent
553
        # modify
554
        # gone
555
        # added
556
        # renamed/reparented and modified
557
        # change kind (perhaps can't be done yet?)
558
        # also, merged in combination with all of these?
559
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
560
        old_a.text_sha1 = '123132'
561
        old_a.text_size = 0
562
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
563
        new_a.text_sha1 = '123132'
564
        new_a.text_size = 0
565
566
        self.assertChangeDescription('unchanged', old_a, new_a)
567
568
        new_a.text_size = 10
569
        new_a.text_sha1 = 'abcabc'
570
        self.assertChangeDescription('modified', old_a, new_a)
571
572
        self.assertChangeDescription('added', None, new_a)
573
        self.assertChangeDescription('removed', old_a, None)
574
        # perhaps a bit questionable but seems like the most reasonable thing...
575
        self.assertChangeDescription('unchanged', None, None)
576
577
        # in this case it's both renamed and modified; show a rename and 
578
        # modification:
579
        new_a.name = 'newfilename'
580
        self.assertChangeDescription('modified and renamed', old_a, new_a)
581
582
        # reparenting is 'renaming'
583
        new_a.name = old_a.name
584
        new_a.parent_id = 'somedir-id'
585
        self.assertChangeDescription('modified and renamed', old_a, new_a)
586
587
        # reset the content values so its not modified
588
        new_a.text_size = old_a.text_size
589
        new_a.text_sha1 = old_a.text_sha1
590
        new_a.name = old_a.name
591
592
        new_a.name = 'newfilename'
593
        self.assertChangeDescription('renamed', old_a, new_a)
594
595
        # reparenting is 'renaming'
596
        new_a.name = old_a.name
597
        new_a.parent_id = 'somedir-id'
598
        self.assertChangeDescription('renamed', old_a, new_a)
599
600
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
601
        change = InventoryEntry.describe_change(old_ie, new_ie)
602
        self.assertEqual(expected_change, change)
603
604
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
605
class TestRevert(TestCaseWithTransport):
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
606
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
607
    def test_dangling_id(self):
608
        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.
609
        wt.lock_tree_write()
610
        self.addCleanup(wt.unlock)
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
611
        self.assertEqual(len(wt.inventory), 1)
612
        open('b1/a', 'wb').write('a test\n')
613
        wt.add('a')
614
        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.
615
        wt.flush() # workaround revert doing wt._write_inventory for now.
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
616
        os.unlink('b1/a')
617
        wt.revert([])
618
        self.assertEqual(len(wt.inventory), 1)
1731.1.39 by Aaron Bentley
Reject removing is_root
619
620
621
class TestIsRoot(TestCase):
622
    """Ensure our root-checking code is accurate."""
623
624
    def test_is_root(self):
625
        inv = Inventory('TREE_ROOT')
626
        self.assertTrue(inv.is_root('TREE_ROOT'))
627
        self.assertFalse(inv.is_root('booga'))
628
        inv.root.file_id = 'booga'
629
        self.assertFalse(inv.is_root('TREE_ROOT'))
630
        self.assertTrue(inv.is_root('booga'))
631
        # works properly even if no root is set
632
        inv.root = None
633
        self.assertFalse(inv.is_root('TREE_ROOT'))
634
        self.assertFalse(inv.is_root('booga'))