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