/brz/remove-bazaar

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