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