/brz/remove-bazaar

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