/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
35
    def test_is_within(self):
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
36
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 \
37
        SRC_FOO_C = pathjoin('src', 'foo.c')
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
38
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
39
                         (['src'], SRC_FOO_C),
968 by Martin Pool
- add some passing tests for is_inside_any
40
                         (['src'], 'src'),
41
                         ]:
42
            self.assert_(is_inside_any(dirs, fn))
43
            
969 by Martin Pool
- Add less-sucky is_within_any
44
        for dirs, fn in [(['src'], 'srccontrol'),
45
                         (['src'], 'srccontrol/foo')]:
46
            self.assertFalse(is_inside_any(dirs, fn))
1740.3.4 by Jelmer Vernooij
Move inventory to commit builder.
47
48
    def test_is_within_or_parent(self):
49
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
50
                         (['src'], 'src/foo.c'),
51
                         (['src/bar.c'], 'src'),
52
                         (['src/bar.c', 'bla/foo.c'], 'src'),
53
                         (['src'], 'src'),
54
                         ]:
55
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
969 by Martin Pool
- Add less-sucky is_within_any
56
            
1740.3.4 by Jelmer Vernooij
Move inventory to commit builder.
57
        for dirs, fn in [(['src'], 'srccontrol'),
58
                         (['srccontrol/foo.c'], 'src'),
59
                         (['src'], 'srccontrol/foo')]:
60
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
61
1102 by Martin Pool
- merge test refactoring from robertc
62
    def test_ids(self):
963 by Martin Pool
- add the start of a test for inventory file-id matching
63
        """Test detection of files within selected directories."""
64
        inv = Inventory()
65
        
66
        for args in [('src', 'directory', 'src-id'), 
67
                     ('doc', 'directory', 'doc-id'), 
68
                     ('src/hello.c', 'file'),
69
                     ('src/bye.c', 'file', 'bye-id'),
70
                     ('Makefile', 'file')]:
71
            inv.add_path(*args)
72
            
73
        self.assertEqual(inv.path2id('src'), 'src-id')
74
        self.assertEqual(inv.path2id('src/bye.c'), 'bye-id')
75
        
76
        self.assert_('src-id' in inv)
1180 by Martin Pool
- start splitting code for xml (de)serialization away from objects
77
1732.1.23 by John Arbash Meinel
Switch iter_entries from being a recursive function and using pathjoin
78
    def test_iter_entries(self):
79
        inv = Inventory()
80
        
81
        for args in [('src', 'directory', 'src-id'), 
82
                     ('doc', 'directory', 'doc-id'), 
83
                     ('src/hello.c', 'file', 'hello-id'),
84
                     ('src/bye.c', 'file', 'bye-id'),
85
                     ('Makefile', 'file', 'makefile-id')]:
86
            inv.add_path(*args)
87
88
        self.assertEqual([
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
89
            ('', ROOT_ID),
1732.1.23 by John Arbash Meinel
Switch iter_entries from being a recursive function and using pathjoin
90
            ('Makefile', 'makefile-id'),
91
            ('doc', 'doc-id'),
92
            ('src', 'src-id'),
93
            ('src/bye.c', 'bye-id'),
94
            ('src/hello.c', 'hello-id'),
95
            ], [(path, ie.file_id) for path, ie in inv.iter_entries()])
96
            
1711.2.36 by John Arbash Meinel
Add an iter_entries_by_dir which returns directory children before their children.
97
    def test_iter_entries_by_dir(self):
98
        inv = Inventory()
99
        
100
        for args in [('src', 'directory', 'src-id'), 
101
                     ('doc', 'directory', 'doc-id'), 
102
                     ('src/hello.c', 'file', 'hello-id'),
103
                     ('src/bye.c', 'file', 'bye-id'),
104
                     ('zz', 'file', 'zz-id'),
105
                     ('src/sub/', 'directory', 'sub-id'),
106
                     ('src/zz.c', 'file', 'zzc-id'),
107
                     ('src/sub/a', 'file', 'a-id'),
108
                     ('Makefile', 'file', 'makefile-id')]:
109
            inv.add_path(*args)
110
111
        self.assertEqual([
1852.6.6 by Robert Collins
Finish updating iter_entries change to make all tests pass.
112
            ('', ROOT_ID),
1711.2.36 by John Arbash Meinel
Add an iter_entries_by_dir which returns directory children before their children.
113
            ('Makefile', 'makefile-id'),
114
            ('doc', 'doc-id'),
115
            ('src', 'src-id'),
116
            ('zz', 'zz-id'),
117
            ('src/bye.c', 'bye-id'),
118
            ('src/hello.c', 'hello-id'),
119
            ('src/sub', 'sub-id'),
120
            ('src/zz.c', 'zzc-id'),
121
            ('src/sub/a', 'a-id'),
122
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
123
            
1180 by Martin Pool
- start splitting code for xml (de)serialization away from objects
124
    def test_version(self):
125
        """Inventory remembers the text's version."""
126
        inv = Inventory()
127
        ie = inv.add_path('foo.txt', 'file')
128
        ## XXX
129
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
130
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
131
class TestInventoryEntry(TestCase):
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
132
133
    def test_file_kind_character(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
134
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
135
        self.assertEqual(file.kind_character(), '')
136
137
    def test_dir_kind_character(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
138
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
139
        self.assertEqual(dir.kind_character(), '/')
140
141
    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
142
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
1399.1.2 by Robert Collins
push kind character creation into InventoryEntry and TreeEntry
143
        self.assertEqual(dir.kind_character(), '')
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
144
145
    def test_dir_detect_changes(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
146
        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
147
        left.text_sha1 = 123
148
        left.executable = True
149
        left.symlink_target='foo'
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
150
        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
151
        right.text_sha1 = 321
152
        right.symlink_target='bar'
153
        self.assertEqual((False, False), left.detect_changes(right))
154
        self.assertEqual((False, False), right.detect_changes(left))
155
156
    def test_file_detect_changes(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
157
        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
158
        left.text_sha1 = 123
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
159
        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
160
        right.text_sha1 = 123
161
        self.assertEqual((False, False), left.detect_changes(right))
162
        self.assertEqual((False, False), right.detect_changes(left))
163
        left.executable = True
164
        self.assertEqual((False, True), left.detect_changes(right))
165
        self.assertEqual((False, True), right.detect_changes(left))
166
        right.text_sha1 = 321
167
        self.assertEqual((True, True), left.detect_changes(right))
168
        self.assertEqual((True, True), right.detect_changes(left))
169
170
    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
171
        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
172
        left.text_sha1 = 123
173
        left.executable = True
174
        left.symlink_target='foo'
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
175
        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
176
        right.text_sha1 = 321
177
        right.symlink_target='foo'
178
        self.assertEqual((False, False), left.detect_changes(right))
179
        self.assertEqual((False, False), right.detect_changes(left))
180
        left.symlink_target = 'different'
181
        self.assertEqual((True, False), left.detect_changes(right))
182
        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
183
1399.1.5 by Robert Collins
move checking whether an entry stores text into inventory.py from fetch,py
184
    def test_file_has_text(self):
1399.1.9 by Robert Collins
factor out file related logic from InventoryEntry to InventoryFile
185
        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
186
        self.failUnless(file.has_text())
187
188
    def test_directory_has_text(self):
1399.1.8 by Robert Collins
factor out inventory directory logic into 'InventoryDirectory' class
189
        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
190
        self.failIf(dir.has_text())
191
192
    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
193
        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
194
        self.failIf(link.has_text())
195
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)
196
    def test_make_entry(self):
197
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
198
            inventory.InventoryFile)
199
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
200
            inventory.InventoryLink)
201
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
202
            inventory.InventoryDirectory)
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
203
1830.3.5 by John Arbash Meinel
make_entry refuses to create non-normalized entries.
204
    def test_make_entry_non_normalized(self):
205
        orig_normalized_filename = osutils.normalized_filename
206
207
        try:
208
            osutils.normalized_filename = osutils._accessible_normalized_filename
209
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
210
            self.assertEqual(u'\xe5', entry.name)
211
            self.assertIsInstance(entry, inventory.InventoryFile)
212
213
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
214
            self.assertRaises(errors.InvalidNormalization,
215
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
216
        finally:
217
            osutils.normalized_filename = orig_normalized_filename
218
219
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
220
class TestEntryDiffing(TestCaseWithTransport):
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
221
222
    def setUp(self):
223
        super(TestEntryDiffing, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
224
        self.wt = self.make_branch_and_tree('.')
225
        self.branch = self.wt.branch
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
226
        print >> open('file', 'wb'), 'foo'
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
227
        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.
228
        self.wt.add(['file'], ['fileid'])
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
229
        self.wt.add(['binfile'], ['binfileid'])
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
230
        if has_symlinks():
231
            os.symlink('target1', 'symlink')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
232
            self.wt.add(['symlink'], ['linkid'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
233
        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
234
        print >> open('file', 'wb'), 'bar'
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
235
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
236
        if has_symlinks():
237
            os.unlink('symlink')
238
            os.symlink('target2', 'symlink')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
239
        self.tree_1 = self.branch.repository.revision_tree('1')
240
        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
241
        self.file_1 = self.inv_1['fileid']
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
242
        self.file_1b = self.inv_1['binfileid']
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
243
        self.tree_2 = self.wt
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
244
        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
245
        self.file_2 = self.inv_2['fileid']
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
246
        self.file_2b = self.inv_2['binfileid']
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
247
        if has_symlinks():
248
            self.link_1 = self.inv_1['linkid']
249
            self.link_2 = self.inv_2['linkid']
250
251
    def test_file_diff_deleted(self):
252
        output = StringIO()
253
        self.file_1.diff(internal_diff, 
254
                          "old_label", self.tree_1,
255
                          "/dev/null", None, None,
256
                          output)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
257
        self.assertEqual(output.getvalue(), "--- old_label\n"
258
                                            "+++ /dev/null\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
259
                                            "@@ -1,1 +0,0 @@\n"
260
                                            "-foo\n"
261
                                            "\n")
262
263
    def test_file_diff_added(self):
264
        output = StringIO()
265
        self.file_1.diff(internal_diff, 
266
                          "new_label", self.tree_1,
267
                          "/dev/null", None, None,
268
                          output, reverse=True)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
269
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
270
                                            "+++ new_label\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
271
                                            "@@ -0,0 +1,1 @@\n"
272
                                            "+foo\n"
273
                                            "\n")
274
275
    def test_file_diff_changed(self):
276
        output = StringIO()
277
        self.file_1.diff(internal_diff, 
278
                          "/dev/null", self.tree_1, 
279
                          "new_label", self.file_2, self.tree_2,
280
                          output)
1740.2.5 by Aaron Bentley
Merge from bzr.dev
281
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
282
                                            "+++ new_label\n"
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
283
                                            "@@ -1,1 +1,1 @@\n"
284
                                            "-foo\n"
285
                                            "+bar\n"
286
                                            "\n")
287
        
1558.15.2 by Aaron Bentley
Implemented binary file handling for diff
288
    def test_file_diff_binary(self):
289
        output = StringIO()
290
        self.file_1.diff(internal_diff, 
291
                          "/dev/null", self.tree_1, 
292
                          "new_label", self.file_2b, self.tree_2,
293
                          output)
1558.15.11 by Aaron Bentley
Apply merge review suggestions
294
        self.assertEqual(output.getvalue(), 
295
                         "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
296
    def test_link_diff_deleted(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
297
        if not has_symlinks():
298
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
299
        output = StringIO()
300
        self.link_1.diff(internal_diff, 
301
                          "old_label", self.tree_1,
302
                          "/dev/null", None, None,
303
                          output)
304
        self.assertEqual(output.getvalue(),
305
                         "=== target was 'target1'\n")
306
307
    def test_link_diff_added(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
308
        if not has_symlinks():
309
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
310
        output = StringIO()
311
        self.link_1.diff(internal_diff, 
312
                          "new_label", self.tree_1,
313
                          "/dev/null", None, None,
314
                          output, reverse=True)
315
        self.assertEqual(output.getvalue(),
316
                         "=== target is 'target1'\n")
317
318
    def test_link_diff_changed(self):
1431 by Robert Collins
BUGFIX: disable symlink support tests when no symlink support is present on the system.
319
        if not has_symlinks():
320
            return
1399.1.4 by Robert Collins
move diff and symlink conditionals into inventory.py from diff.py
321
        output = StringIO()
322
        self.link_1.diff(internal_diff, 
323
                          "/dev/null", self.tree_1, 
324
                          "new_label", self.link_2, self.tree_2,
325
                          output)
326
        self.assertEqual(output.getvalue(),
327
                         "=== target changed 'target1' => 'target2'\n")
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
328
329
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
330
class TestSnapshot(TestCaseWithTransport):
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
331
332
    def setUp(self):
333
        # for full testing we'll need a branch
334
        # with a subdir to test parent changes.
335
        # and a file, link and dir under that.
336
        # but right now I only need one attribute
337
        # to change, and then test merge patterns
338
        # with fake parent entries.
339
        super(TestSnapshot, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
340
        self.wt = self.make_branch_and_tree('.')
341
        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
342
        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.
343
        self.wt.add(['subdir', 'subdir/file'],
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
344
                                       ['dirid', 'fileid'])
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
345
        if has_symlinks():
346
            pass
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
347
        self.wt.commit('message_1', rev_id = '1')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
348
        self.tree_1 = self.branch.repository.revision_tree('1')
349
        self.inv_1 = self.branch.repository.get_inventory('1')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
350
        self.file_1 = self.inv_1['fileid']
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
351
        self.file_active = self.wt.inventory['fileid']
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
352
        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
353
354
    def test_snapshot_new_revision(self):
355
        # This tests that a simple commit with no parents makes a new
356
        # revision value in the inventory entry
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
357
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
358
        # expected outcome - file_1 has a revision id of '2', and we can get
359
        # its text of 'file contents' out of the weave.
360
        self.assertEqual(self.file_1.revision, '1')
361
        self.assertEqual(self.file_active.revision, '2')
362
        # 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.
363
        lines = self.branch.repository.weave_store.get_weave(
364
            'fileid', 
365
            self.branch.get_transaction()).get_lines('2')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
366
        self.assertEqual(lines, ['contents of subdir/file\n'])
367
368
    def test_snapshot_unchanged(self):
369
        #This tests that a simple commit does not make a new entry for
370
        # an unchanged inventory entry
371
        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.
372
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
373
        self.assertEqual(self.file_1.revision, '1')
374
        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.
375
        vf = self.branch.repository.weave_store.get_weave(
376
            'fileid', 
377
            self.branch.repository.get_transaction())
1563.2.1 by Robert Collins
Merge in a variation of the versionedfile api from versioned-file.
378
        self.assertRaises(errors.RevisionNotPresent,
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
379
                          vf.get_lines,
380
                          '2')
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
381
382
    def test_snapshot_merge_identical_different_revid(self):
383
        # This tests that a commit with two identical parents, one of which has
384
        # 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
385
        # 1->other, commit a merge of other against 1, results in 2.
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
386
        other_ie = inventory.InventoryFile('fileid', 'newname', self.file_1.parent_id)
387
        other_ie = inventory.InventoryFile('fileid', 'file', self.file_1.parent_id)
388
        other_ie.revision = '1'
389
        other_ie.text_sha1 = self.file_1.text_sha1
390
        other_ie.text_size = self.file_1.text_size
391
        self.assertEqual(self.file_1, other_ie)
392
        other_ie.revision = 'other'
393
        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.
394
        versionfile = self.branch.repository.weave_store.get_weave(
395
            'fileid', self.branch.repository.get_transaction())
396
        versionfile.clone_text('other', '1', ['1'])
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
397
        self.file_active.snapshot('2', 'subdir/file', 
398
                                  {'1':self.file_1, 'other':other_ie},
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
399
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
400
        self.assertEqual(self.file_active.revision, '2')
401
402
    def test_snapshot_changed(self):
403
        # This tests that a commit with one different parent results in a new
404
        # revision id in the entry.
405
        self.file_active.name='newname'
406
        rename('subdir/file', 'subdir/newname')
407
        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.
408
                                  self.wt, self.builder)
1407 by Robert Collins
define some expected behaviour for inventory_entry.snapshot
409
        # expected outcome - file_1 has a revision id of '2'
410
        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.
411
412
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
413
class TestPreviousHeads(TestCaseWithTransport):
1411 by Robert Collins
use weave ancestry to determine inventory entry previous heads, prevent propogating 'I did a merge' merges.
414
415
    def setUp(self):
416
        # we want several inventories, that respectively
417
        # give use the following scenarios:
418
        # A) fileid not in any inventory (A),
419
        # B) fileid present in one inventory (B) and (A,B)
420
        # C) fileid present in two inventories, and they
421
        #   are not mutual descendents (B, C)
422
        # D) fileid present in two inventories and one is
423
        #   a descendent of the other. (B, D)
424
        super(TestPreviousHeads, self).setUp()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
425
        self.wt = self.make_branch_and_tree('.')
426
        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.
427
        self.build_tree(['file'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
428
        self.wt.commit('new branch', allow_pointless=True, rev_id='A')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
429
        self.inv_A = self.branch.repository.get_inventory('A')
1185.65.13 by Robert Collins
Merge from integration
430
        self.wt.add(['file'], ['fileid'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
431
        self.wt.commit('add file', rev_id='B')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
432
        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
433
        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.
434
        self.assertEqual(self.branch.revision_history(), ['A'])
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
435
        self.wt.commit('another add of file', rev_id='C')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
436
        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.
437
        self.wt.add_parent_tree_id('B')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
438
        self.wt.commit('merge in B', rev_id='D')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
439
        self.inv_D = self.branch.repository.get_inventory('D')
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
440
        self.file_active = self.wt.inventory['fileid']
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
441
        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.
442
            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.
443
        
444
    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.
445
        return self.file_active.find_previous_heads(
446
            inventories, 
447
            self.branch.repository.weave_store,
448
            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.
449
        
450
    def test_fileid_in_no_inventory(self):
451
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
452
453
    def test_fileid_in_one_inventory(self):
454
        self.assertEqual({'B':self.inv_B['fileid']},
455
                         self.get_previous_heads([self.inv_B]))
456
        self.assertEqual({'B':self.inv_B['fileid']},
457
                         self.get_previous_heads([self.inv_A, self.inv_B]))
458
        self.assertEqual({'B':self.inv_B['fileid']},
459
                         self.get_previous_heads([self.inv_B, self.inv_A]))
460
461
    def test_fileid_in_two_inventories_gives_both_entries(self):
462
        self.assertEqual({'B':self.inv_B['fileid'],
463
                          'C':self.inv_C['fileid']},
464
                          self.get_previous_heads([self.inv_B, self.inv_C]))
465
        self.assertEqual({'B':self.inv_B['fileid'],
466
                          'C':self.inv_C['fileid']},
467
                          self.get_previous_heads([self.inv_C, self.inv_B]))
468
469
    def test_fileid_in_two_inventories_already_merged_gives_head(self):
470
        self.assertEqual({'D':self.inv_D['fileid']},
471
                         self.get_previous_heads([self.inv_B, self.inv_D]))
472
        self.assertEqual({'D':self.inv_D['fileid']},
473
                         self.get_previous_heads([self.inv_D, self.inv_B]))
474
475
    # 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
476
477
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
478
class TestDescribeChanges(TestCase):
479
480
    def test_describe_change(self):
481
        # we need to test the following change combinations:
482
        # rename
483
        # reparent
484
        # modify
485
        # gone
486
        # added
487
        # renamed/reparented and modified
488
        # change kind (perhaps can't be done yet?)
489
        # also, merged in combination with all of these?
490
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
491
        old_a.text_sha1 = '123132'
492
        old_a.text_size = 0
493
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
494
        new_a.text_sha1 = '123132'
495
        new_a.text_size = 0
496
497
        self.assertChangeDescription('unchanged', old_a, new_a)
498
499
        new_a.text_size = 10
500
        new_a.text_sha1 = 'abcabc'
501
        self.assertChangeDescription('modified', old_a, new_a)
502
503
        self.assertChangeDescription('added', None, new_a)
504
        self.assertChangeDescription('removed', old_a, None)
505
        # perhaps a bit questionable but seems like the most reasonable thing...
506
        self.assertChangeDescription('unchanged', None, None)
507
508
        # in this case it's both renamed and modified; show a rename and 
509
        # modification:
510
        new_a.name = 'newfilename'
511
        self.assertChangeDescription('modified and renamed', old_a, new_a)
512
513
        # reparenting is 'renaming'
514
        new_a.name = old_a.name
515
        new_a.parent_id = 'somedir-id'
516
        self.assertChangeDescription('modified and renamed', old_a, new_a)
517
518
        # reset the content values so its not modified
519
        new_a.text_size = old_a.text_size
520
        new_a.text_sha1 = old_a.text_sha1
521
        new_a.name = old_a.name
522
523
        new_a.name = 'newfilename'
524
        self.assertChangeDescription('renamed', old_a, new_a)
525
526
        # reparenting is 'renaming'
527
        new_a.name = old_a.name
528
        new_a.parent_id = 'somedir-id'
529
        self.assertChangeDescription('renamed', old_a, new_a)
530
531
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
532
        change = InventoryEntry.describe_change(old_ie, new_ie)
533
        self.assertEqual(expected_change, change)
534
535
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
536
class TestRevert(TestCaseWithTransport):
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
537
1534.7.178 by Aaron Bentley
Fixed dangling inventory ids in revert
538
    def test_dangling_id(self):
539
        wt = self.make_branch_and_tree('b1')
540
        self.assertEqual(len(wt.inventory), 1)
541
        open('b1/a', 'wb').write('a test\n')
542
        wt.add('a')
543
        self.assertEqual(len(wt.inventory), 2)
544
        os.unlink('b1/a')
545
        wt.revert([])
546
        self.assertEqual(len(wt.inventory), 1)
1731.1.39 by Aaron Bentley
Reject removing is_root
547
548
549
class TestIsRoot(TestCase):
550
    """Ensure our root-checking code is accurate."""
551
552
    def test_is_root(self):
553
        inv = Inventory('TREE_ROOT')
554
        self.assertTrue(inv.is_root('TREE_ROOT'))
555
        self.assertFalse(inv.is_root('booga'))
556
        inv.root.file_id = 'booga'
557
        self.assertFalse(inv.is_root('TREE_ROOT'))
558
        self.assertTrue(inv.is_root('booga'))
559
        # works properly even if no root is set
560
        inv.root = None
561
        self.assertFalse(inv.is_root('TREE_ROOT'))
562
        self.assertFalse(inv.is_root('booga'))