/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_commit.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2018-08-20 21:41:54 UTC
  • mfrom: (7067.2.2 python3-selftest)
  • Revision ID: breezy.the.bot@gmail.com-20180820214154-ls3f4lfwrdzs2k0t
Fix most selftest tests on Python 3.

Merged from https://code.launchpad.net/~jelmer/brz/python3-selftest/+merge/353202

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005-2012, 2016 Canonical Ltd
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
import os
19
19
 
20
 
import bzrlib
21
 
from bzrlib.tests import TestCaseWithTransport
22
 
from bzrlib.branch import Branch
23
 
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
24
 
from bzrlib.workingtree import WorkingTree
25
 
from bzrlib.commit import Commit
26
 
from bzrlib.config import BranchConfig
27
 
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed, 
28
 
                           LockContention)
 
20
import breezy
 
21
from .. import (
 
22
    config,
 
23
    controldir,
 
24
    errors,
 
25
    )
 
26
from ..branch import Branch
 
27
from ..bzr.bzrdir import BzrDirMetaFormat1
 
28
from ..commit import (
 
29
    CannotCommitSelectedFileMerge,
 
30
    Commit,
 
31
    NullCommitReporter,
 
32
    PointlessCommit,
 
33
    filter_excluded,
 
34
    )
 
35
from ..errors import (
 
36
    BzrError,
 
37
    LockContention,
 
38
    )
 
39
from . import (
 
40
    TestCase,
 
41
    TestCaseWithTransport,
 
42
    test_foreign,
 
43
    )
 
44
from .features import (
 
45
    SymlinkFeature,
 
46
    )
 
47
from .matchers import MatchesAncestry
29
48
 
30
49
 
31
50
# TODO: Test commit with some added, and added-but-missing files
32
51
 
33
 
class MustSignConfig(BranchConfig):
34
 
 
35
 
    def signature_needed(self):
 
52
class MustSignConfig(config.MemoryStack):
 
53
 
 
54
    def __init__(self):
 
55
        super(MustSignConfig, self).__init__(b'''
 
56
create_signatures=always
 
57
''')
 
58
 
 
59
 
 
60
class CapturingReporter(NullCommitReporter):
 
61
    """This reporter captures the calls made to it for evaluation later."""
 
62
 
 
63
    def __init__(self):
 
64
        # a list of the calls this received
 
65
        self.calls = []
 
66
 
 
67
    def snapshot_change(self, change, path):
 
68
        self.calls.append(('change', change, path))
 
69
 
 
70
    def deleted(self, file_id):
 
71
        self.calls.append(('deleted', file_id))
 
72
 
 
73
    def missing(self, path):
 
74
        self.calls.append(('missing', path))
 
75
 
 
76
    def renamed(self, change, old_path, new_path):
 
77
        self.calls.append(('renamed', change, old_path, new_path))
 
78
 
 
79
    def is_verbose(self):
36
80
        return True
37
81
 
38
 
    def gpg_signing_command(self):
39
 
        return ['cat', '-']
40
 
 
41
 
 
42
 
class BranchWithHooks(BranchConfig):
43
 
 
44
 
    def post_commit(self):
45
 
        return "bzrlib.ahook bzrlib.ahook"
46
 
 
47
82
 
48
83
class TestCommit(TestCaseWithTransport):
49
84
 
51
86
        """Commit and check two versions of a single file."""
52
87
        wt = self.make_branch_and_tree('.')
53
88
        b = wt.branch
54
 
        file('hello', 'w').write('hello world')
 
89
        with open('hello', 'w') as f: f.write('hello world')
55
90
        wt.add('hello')
56
 
        wt.commit(message='add hello')
57
 
        file_id = wt.path2id('hello')
58
 
 
59
 
        file('hello', 'w').write('version 2')
60
 
        wt.commit(message='commit 2')
61
 
 
62
 
        eq = self.assertEquals
 
91
        rev1 = wt.commit(message='add hello')
 
92
 
 
93
        with open('hello', 'w') as f: f.write('version 2')
 
94
        rev2 = wt.commit(message='commit 2')
 
95
 
 
96
        eq = self.assertEqual
63
97
        eq(b.revno(), 2)
64
 
        rh = b.revision_history()
65
 
        rev = b.repository.get_revision(rh[0])
 
98
        rev = b.repository.get_revision(rev1)
66
99
        eq(rev.message, 'add hello')
67
100
 
68
 
        tree1 = b.repository.revision_tree(rh[0])
69
 
        text = tree1.get_file_text(file_id)
70
 
        eq(text, 'hello world')
71
 
 
72
 
        tree2 = b.repository.revision_tree(rh[1])
73
 
        eq(tree2.get_file_text(file_id), 'version 2')
74
 
 
75
 
    def test_delete_commit(self):
76
 
        """Test a commit with a deleted file"""
77
 
        wt = self.make_branch_and_tree('.')
78
 
        b = wt.branch
79
 
        file('hello', 'w').write('hello world')
80
 
        wt.add(['hello'], ['hello-id'])
 
101
        tree1 = b.repository.revision_tree(rev1)
 
102
        tree1.lock_read()
 
103
        text = tree1.get_file_text('hello')
 
104
        tree1.unlock()
 
105
        self.assertEqual(b'hello world', text)
 
106
 
 
107
        tree2 = b.repository.revision_tree(rev2)
 
108
        tree2.lock_read()
 
109
        text = tree2.get_file_text('hello')
 
110
        tree2.unlock()
 
111
        self.assertEqual(b'version 2', text)
 
112
 
 
113
    def test_commit_lossy_native(self):
 
114
        """Attempt a lossy commit to a native branch."""
 
115
        wt = self.make_branch_and_tree('.')
 
116
        b = wt.branch
 
117
        with open('hello', 'w') as f: f.write('hello world')
 
118
        wt.add('hello')
 
119
        revid = wt.commit(message='add hello', rev_id=b'revid', lossy=True)
 
120
        self.assertEqual(b'revid', revid)
 
121
 
 
122
    def test_commit_lossy_foreign(self):
 
123
        """Attempt a lossy commit to a foreign branch."""
 
124
        test_foreign.register_dummy_foreign_for_test(self)
 
125
        wt = self.make_branch_and_tree('.',
 
126
            format=test_foreign.DummyForeignVcsDirFormat())
 
127
        b = wt.branch
 
128
        with open('hello', 'w') as f: f.write('hello world')
 
129
        wt.add('hello')
 
130
        revid = wt.commit(message='add hello', lossy=True,
 
131
            timestamp=1302659388, timezone=0)
 
132
        self.assertEqual(b'dummy-v1:1302659388-0-UNKNOWN', revid)
 
133
 
 
134
    def test_commit_bound_lossy_foreign(self):
 
135
        """Attempt a lossy commit to a bzr branch bound to a foreign branch."""
 
136
        test_foreign.register_dummy_foreign_for_test(self)
 
137
        foreign_branch = self.make_branch('foreign',
 
138
            format=test_foreign.DummyForeignVcsDirFormat())
 
139
        wt = foreign_branch.create_checkout("local")
 
140
        b = wt.branch
 
141
        with open('local/hello', 'w') as f: f.write('hello world')
 
142
        wt.add('hello')
 
143
        revid = wt.commit(message='add hello', lossy=True,
 
144
            timestamp=1302659388, timezone=0)
 
145
        self.assertEqual(b'dummy-v1:1302659388-0-0', revid)
 
146
        self.assertEqual(b'dummy-v1:1302659388-0-0',
 
147
            foreign_branch.last_revision())
 
148
        self.assertEqual(b'dummy-v1:1302659388-0-0',
 
149
            wt.branch.last_revision())
 
150
 
 
151
    def test_missing_commit(self):
 
152
        """Test a commit with a missing file"""
 
153
        wt = self.make_branch_and_tree('.')
 
154
        b = wt.branch
 
155
        with open('hello', 'w') as f: f.write('hello world')
 
156
        wt.add(['hello'], [b'hello-id'])
81
157
        wt.commit(message='add hello')
82
158
 
83
159
        os.remove('hello')
84
 
        wt.commit('removed hello', rev_id='rev2')
85
 
 
86
 
        tree = b.repository.revision_tree('rev2')
87
 
        self.assertFalse(tree.has_id('hello-id'))
 
160
        reporter = CapturingReporter()
 
161
        wt.commit('removed hello', rev_id=b'rev2', reporter=reporter)
 
162
        self.assertEqual(
 
163
            [('missing', u'hello'), ('deleted', u'hello')],
 
164
            reporter.calls)
 
165
 
 
166
        tree = b.repository.revision_tree(b'rev2')
 
167
        self.assertFalse(tree.has_id(b'hello-id'))
 
168
 
 
169
    def test_partial_commit_move(self):
 
170
        """Test a partial commit where a file was renamed but not committed.
 
171
 
 
172
        https://bugs.launchpad.net/bzr/+bug/83039
 
173
 
 
174
        If not handled properly, commit will try to snapshot
 
175
        dialog.py with olive/ as a parent, while
 
176
        olive/ has not been snapshotted yet.
 
177
        """
 
178
        wt = self.make_branch_and_tree('.')
 
179
        b = wt.branch
 
180
        self.build_tree(['annotate/', 'annotate/foo.py',
 
181
                         'olive/', 'olive/dialog.py'
 
182
                        ])
 
183
        wt.add(['annotate', 'olive', 'annotate/foo.py', 'olive/dialog.py'])
 
184
        wt.commit(message='add files')
 
185
        wt.rename_one("olive/dialog.py", "aaa")
 
186
        self.build_tree_contents([('annotate/foo.py', b'modified\n')])
 
187
        wt.commit('renamed hello', specific_files=["annotate"])
88
188
 
89
189
    def test_pointless_commit(self):
90
190
        """Commit refuses unless there are changes or it's forced."""
91
191
        wt = self.make_branch_and_tree('.')
92
192
        b = wt.branch
93
 
        file('hello', 'w').write('hello')
 
193
        with open('hello', 'w') as f: f.write('hello')
94
194
        wt.add(['hello'])
95
195
        wt.commit(message='add hello')
96
 
        self.assertEquals(b.revno(), 1)
 
196
        self.assertEqual(b.revno(), 1)
97
197
        self.assertRaises(PointlessCommit,
98
198
                          wt.commit,
99
199
                          message='fails',
100
200
                          allow_pointless=False)
101
 
        self.assertEquals(b.revno(), 1)
102
 
        
 
201
        self.assertEqual(b.revno(), 1)
 
202
 
103
203
    def test_commit_empty(self):
104
204
        """Commiting an empty tree works."""
105
205
        wt = self.make_branch_and_tree('.')
110
210
                          message='empty tree',
111
211
                          allow_pointless=False)
112
212
        wt.commit(message='empty tree', allow_pointless=True)
113
 
        self.assertEquals(b.revno(), 2)
 
213
        self.assertEqual(b.revno(), 2)
114
214
 
115
215
    def test_selective_delete(self):
116
216
        """Selective commit in tree with deletions"""
117
217
        wt = self.make_branch_and_tree('.')
118
218
        b = wt.branch
119
 
        file('hello', 'w').write('hello')
120
 
        file('buongia', 'w').write('buongia')
 
219
        with open('hello', 'w') as f: f.write('hello')
 
220
        with open('buongia', 'w') as f: f.write('buongia')
121
221
        wt.add(['hello', 'buongia'],
122
 
              ['hello-id', 'buongia-id'])
 
222
              [b'hello-id', b'buongia-id'])
123
223
        wt.commit(message='add files',
124
 
                 rev_id='test@rev-1')
125
 
        
 
224
                 rev_id=b'test@rev-1')
 
225
 
126
226
        os.remove('hello')
127
 
        file('buongia', 'w').write('new text')
 
227
        with open('buongia', 'w') as f: f.write('new text')
128
228
        wt.commit(message='update text',
129
229
                 specific_files=['buongia'],
130
230
                 allow_pointless=False,
131
 
                 rev_id='test@rev-2')
 
231
                 rev_id=b'test@rev-2')
132
232
 
133
233
        wt.commit(message='remove hello',
134
234
                 specific_files=['hello'],
135
235
                 allow_pointless=False,
136
 
                 rev_id='test@rev-3')
 
236
                 rev_id=b'test@rev-3')
137
237
 
138
 
        eq = self.assertEquals
 
238
        eq = self.assertEqual
139
239
        eq(b.revno(), 3)
140
240
 
141
 
        tree2 = b.repository.revision_tree('test@rev-2')
 
241
        tree2 = b.repository.revision_tree(b'test@rev-2')
 
242
        tree2.lock_read()
 
243
        self.addCleanup(tree2.unlock)
142
244
        self.assertTrue(tree2.has_filename('hello'))
143
 
        self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
144
 
        self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
145
 
        
146
 
        tree3 = b.repository.revision_tree('test@rev-3')
 
245
        self.assertEqual(tree2.get_file_text('hello'), b'hello')
 
246
        self.assertEqual(tree2.get_file_text('buongia'), b'new text')
 
247
 
 
248
        tree3 = b.repository.revision_tree(b'test@rev-3')
 
249
        tree3.lock_read()
 
250
        self.addCleanup(tree3.unlock)
147
251
        self.assertFalse(tree3.has_filename('hello'))
148
 
        self.assertEquals(tree3.get_file_text('buongia-id'), 'new text')
 
252
        self.assertEqual(tree3.get_file_text('buongia'), b'new text')
149
253
 
150
254
    def test_commit_rename(self):
151
255
        """Test commit of a revision where a file is renamed."""
152
256
        tree = self.make_branch_and_tree('.')
153
257
        b = tree.branch
154
258
        self.build_tree(['hello'], line_endings='binary')
155
 
        tree.add(['hello'], ['hello-id'])
156
 
        tree.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
 
259
        tree.add(['hello'], [b'hello-id'])
 
260
        tree.commit(message='one', rev_id=b'test@rev-1', allow_pointless=False)
157
261
 
158
262
        tree.rename_one('hello', 'fruity')
159
 
        tree.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
 
263
        tree.commit(message='renamed', rev_id=b'test@rev-2', allow_pointless=False)
160
264
 
161
 
        eq = self.assertEquals
162
 
        tree1 = b.repository.revision_tree('test@rev-1')
163
 
        eq(tree1.id2path('hello-id'), 'hello')
164
 
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
 
265
        eq = self.assertEqual
 
266
        tree1 = b.repository.revision_tree(b'test@rev-1')
 
267
        tree1.lock_read()
 
268
        self.addCleanup(tree1.unlock)
 
269
        eq(tree1.id2path(b'hello-id'), 'hello')
 
270
        eq(tree1.get_file_text('hello'), b'contents of hello\n')
165
271
        self.assertFalse(tree1.has_filename('fruity'))
166
 
        self.check_inventory_shape(tree1.inventory, ['hello'])
167
 
        ie = tree1.inventory['hello-id']
168
 
        eq(ie.revision, 'test@rev-1')
 
272
        self.check_tree_shape(tree1, ['hello'])
 
273
        eq(tree1.get_file_revision('hello'), b'test@rev-1')
169
274
 
170
 
        tree2 = b.repository.revision_tree('test@rev-2')
171
 
        eq(tree2.id2path('hello-id'), 'fruity')
172
 
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
173
 
        self.check_inventory_shape(tree2.inventory, ['fruity'])
174
 
        ie = tree2.inventory['hello-id']
175
 
        eq(ie.revision, 'test@rev-2')
 
275
        tree2 = b.repository.revision_tree(b'test@rev-2')
 
276
        tree2.lock_read()
 
277
        self.addCleanup(tree2.unlock)
 
278
        eq(tree2.id2path(b'hello-id'), 'fruity')
 
279
        eq(tree2.get_file_text('fruity'), b'contents of hello\n')
 
280
        self.check_tree_shape(tree2, ['fruity'])
 
281
        eq(tree2.get_file_revision('fruity'), b'test@rev-2')
176
282
 
177
283
    def test_reused_rev_id(self):
178
284
        """Test that a revision id cannot be reused in a branch"""
179
285
        wt = self.make_branch_and_tree('.')
180
286
        b = wt.branch
181
 
        wt.commit('initial', rev_id='test@rev-1', allow_pointless=True)
 
287
        wt.commit('initial', rev_id=b'test@rev-1', allow_pointless=True)
182
288
        self.assertRaises(Exception,
183
289
                          wt.commit,
184
290
                          message='reused id',
185
 
                          rev_id='test@rev-1',
 
291
                          rev_id=b'test@rev-1',
186
292
                          allow_pointless=True)
187
293
 
188
294
    def test_commit_move(self):
189
295
        """Test commit of revisions with moved files and directories"""
190
 
        eq = self.assertEquals
 
296
        eq = self.assertEqual
191
297
        wt = self.make_branch_and_tree('.')
192
298
        b = wt.branch
193
 
        r1 = 'test@rev-1'
 
299
        r1 = b'test@rev-1'
194
300
        self.build_tree(['hello', 'a/', 'b/'])
195
 
        wt.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
 
301
        wt.add(['hello', 'a', 'b'], [b'hello-id', b'a-id', b'b-id'])
196
302
        wt.commit('initial', rev_id=r1, allow_pointless=False)
197
303
        wt.move(['hello'], 'a')
198
 
        r2 = 'test@rev-2'
 
304
        r2 = b'test@rev-2'
199
305
        wt.commit('two', rev_id=r2, allow_pointless=False)
200
 
        self.check_inventory_shape(wt.read_working_inventory(),
201
 
                                   ['a', 'a/hello', 'b'])
 
306
        wt.lock_read()
 
307
        try:
 
308
            self.check_tree_shape(wt, ['a/', 'a/hello', 'b/'])
 
309
        finally:
 
310
            wt.unlock()
202
311
 
203
312
        wt.move(['b'], 'a')
204
 
        r3 = 'test@rev-3'
 
313
        r3 = b'test@rev-3'
205
314
        wt.commit('three', rev_id=r3, allow_pointless=False)
206
 
        self.check_inventory_shape(wt.read_working_inventory(),
207
 
                                   ['a', 'a/hello', 'a/b'])
208
 
        self.check_inventory_shape(b.repository.get_revision_inventory(r3),
209
 
                                   ['a', 'a/hello', 'a/b'])
 
315
        wt.lock_read()
 
316
        try:
 
317
            self.check_tree_shape(wt,
 
318
                                       ['a/', 'a/hello', 'a/b/'])
 
319
            self.check_tree_shape(b.repository.revision_tree(r3),
 
320
                                       ['a/', 'a/hello', 'a/b/'])
 
321
        finally:
 
322
            wt.unlock()
210
323
 
211
324
        wt.move(['a/hello'], 'a/b')
212
 
        r4 = 'test@rev-4'
 
325
        r4 = b'test@rev-4'
213
326
        wt.commit('four', rev_id=r4, allow_pointless=False)
214
 
        self.check_inventory_shape(wt.read_working_inventory(),
215
 
                                   ['a', 'a/b/hello', 'a/b'])
216
 
 
217
 
        inv = b.repository.get_revision_inventory(r4)
218
 
        eq(inv['hello-id'].revision, r4)
219
 
        eq(inv['a-id'].revision, r1)
220
 
        eq(inv['b-id'].revision, r3)
221
 
        
 
327
        wt.lock_read()
 
328
        try:
 
329
            self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
 
330
        finally:
 
331
            wt.unlock()
 
332
 
 
333
        inv = b.repository.get_inventory(r4)
 
334
        eq(inv.get_entry(b'hello-id').revision, r4)
 
335
        eq(inv.get_entry(b'a-id').revision, r1)
 
336
        eq(inv.get_entry(b'b-id').revision, r3)
 
337
 
222
338
    def test_removed_commit(self):
223
339
        """Commit with a removed file"""
224
340
        wt = self.make_branch_and_tree('.')
225
341
        b = wt.branch
226
 
        file('hello', 'w').write('hello world')
227
 
        wt.add(['hello'], ['hello-id'])
 
342
        with open('hello', 'w') as f: f.write('hello world')
 
343
        wt.add(['hello'], [b'hello-id'])
228
344
        wt.commit(message='add hello')
229
345
        wt.remove('hello')
230
 
        wt.commit('removed hello', rev_id='rev2')
 
346
        wt.commit('removed hello', rev_id=b'rev2')
231
347
 
232
 
        tree = b.repository.revision_tree('rev2')
233
 
        self.assertFalse(tree.has_id('hello-id'))
 
348
        tree = b.repository.revision_tree(b'rev2')
 
349
        self.assertFalse(tree.has_id(b'hello-id'))
234
350
 
235
351
    def test_committed_ancestry(self):
236
352
        """Test commit appends revisions to ancestry."""
238
354
        b = wt.branch
239
355
        rev_ids = []
240
356
        for i in range(4):
241
 
            file('hello', 'w').write((str(i) * 4) + '\n')
 
357
            with open('hello', 'w') as f: f.write((str(i) * 4) + '\n')
242
358
            if i == 0:
243
 
                wt.add(['hello'], ['hello-id'])
244
 
            rev_id = 'test@rev-%d' % (i+1)
 
359
                wt.add(['hello'], [b'hello-id'])
 
360
            rev_id = b'test@rev-%d' % (i+1)
245
361
            rev_ids.append(rev_id)
246
362
            wt.commit(message='rev %d' % (i+1),
247
363
                     rev_id=rev_id)
248
 
        eq = self.assertEquals
249
 
        eq(b.revision_history(), rev_ids)
250
364
        for i in range(4):
251
 
            anc = b.repository.get_ancestry(rev_ids[i])
252
 
            eq(anc, [None] + rev_ids[:i+1])
 
365
            self.assertThat(rev_ids[:i+1],
 
366
                MatchesAncestry(b.repository, rev_ids[i]))
253
367
 
254
368
    def test_commit_new_subdir_child_selective(self):
255
369
        wt = self.make_branch_and_tree('.')
256
370
        b = wt.branch
257
371
        self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
258
372
        wt.add(['dir', 'dir/file1', 'dir/file2'],
259
 
              ['dirid', 'file1id', 'file2id'])
260
 
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
261
 
        inv = b.repository.get_inventory('1')
262
 
        self.assertEqual('1', inv['dirid'].revision)
263
 
        self.assertEqual('1', inv['file1id'].revision)
 
373
              [b'dirid', b'file1id', b'file2id'])
 
374
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id=b'1')
 
375
        inv = b.repository.get_inventory(b'1')
 
376
        self.assertEqual(b'1', inv.get_entry(b'dirid').revision)
 
377
        self.assertEqual(b'1', inv.get_entry(b'file1id').revision)
264
378
        # FIXME: This should raise a KeyError I think, rbc20051006
265
 
        self.assertRaises(BzrError, inv.__getitem__, 'file2id')
 
379
        self.assertRaises(BzrError, inv.get_entry, b'file2id')
266
380
 
267
381
    def test_strict_commit(self):
268
382
        """Try and commit with unknown files and strict = True, should fail."""
269
 
        from bzrlib.errors import StrictCommitFailed
 
383
        from ..errors import StrictCommitFailed
270
384
        wt = self.make_branch_and_tree('.')
271
385
        b = wt.branch
272
 
        file('hello', 'w').write('hello world')
 
386
        with open('hello', 'w') as f: f.write('hello world')
273
387
        wt.add('hello')
274
 
        file('goodbye', 'w').write('goodbye cruel world!')
 
388
        with open('goodbye', 'w') as f: f.write('goodbye cruel world!')
275
389
        self.assertRaises(StrictCommitFailed, wt.commit,
276
390
            message='add hello but not goodbye', strict=True)
277
391
 
278
392
    def test_strict_commit_without_unknowns(self):
279
393
        """Try and commit with no unknown files and strict = True,
280
394
        should work."""
281
 
        from bzrlib.errors import StrictCommitFailed
282
395
        wt = self.make_branch_and_tree('.')
283
396
        b = wt.branch
284
 
        file('hello', 'w').write('hello world')
 
397
        with open('hello', 'w') as f: f.write('hello world')
285
398
        wt.add('hello')
286
399
        wt.commit(message='add hello', strict=True)
287
400
 
289
402
        """Try and commit with unknown files and strict = False, should work."""
290
403
        wt = self.make_branch_and_tree('.')
291
404
        b = wt.branch
292
 
        file('hello', 'w').write('hello world')
 
405
        with open('hello', 'w') as f: f.write('hello world')
293
406
        wt.add('hello')
294
 
        file('goodbye', 'w').write('goodbye cruel world!')
 
407
        with open('goodbye', 'w') as f: f.write('goodbye cruel world!')
295
408
        wt.commit(message='add hello but not goodbye', strict=False)
296
409
 
297
410
    def test_nonstrict_commit_without_unknowns(self):
299
412
        should work."""
300
413
        wt = self.make_branch_and_tree('.')
301
414
        b = wt.branch
302
 
        file('hello', 'w').write('hello world')
 
415
        with open('hello', 'w') as f: f.write('hello world')
303
416
        wt.add('hello')
304
417
        wt.commit(message='add hello', strict=False)
305
418
 
306
419
    def test_signed_commit(self):
307
 
        import bzrlib.gpg
308
 
        import bzrlib.commit as commit
309
 
        oldstrategy = bzrlib.gpg.GPGStrategy
 
420
        import breezy.gpg
 
421
        import breezy.commit as commit
 
422
        oldstrategy = breezy.gpg.GPGStrategy
310
423
        wt = self.make_branch_and_tree('.')
311
424
        branch = wt.branch
312
 
        wt.commit("base", allow_pointless=True, rev_id='A')
313
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
425
        wt.commit("base", allow_pointless=True, rev_id=b'A')
 
426
        self.assertFalse(branch.repository.has_signature_for_revision_id(b'A'))
314
427
        try:
315
 
            from bzrlib.testament import Testament
 
428
            from ..testament import Testament
316
429
            # monkey patch gpg signing mechanism
317
 
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
318
 
            commit.Commit(config=MustSignConfig(branch)).commit(message="base",
319
 
                                                      allow_pointless=True,
320
 
                                                      rev_id='B',
321
 
                                                      working_tree=wt)
322
 
            self.assertEqual(Testament.from_revision(branch.repository,
323
 
                             'B').as_short_text(),
324
 
                             branch.repository.get_signature_text('B'))
 
430
            breezy.gpg.GPGStrategy = breezy.gpg.LoopbackGPGStrategy
 
431
            conf = config.MemoryStack(b'''
 
432
create_signatures=always
 
433
''')
 
434
            commit.Commit(config_stack=conf).commit(
 
435
                message="base", allow_pointless=True, rev_id=b'B',
 
436
                working_tree=wt)
 
437
            def sign(text):
 
438
                return breezy.gpg.LoopbackGPGStrategy(None).sign(
 
439
                        text, breezy.gpg.MODE_CLEAR)
 
440
            self.assertEqual(sign(Testament.from_revision(branch.repository,
 
441
                                                          b'B').as_short_text()),
 
442
                             branch.repository.get_signature_text(b'B'))
325
443
        finally:
326
 
            bzrlib.gpg.GPGStrategy = oldstrategy
 
444
            breezy.gpg.GPGStrategy = oldstrategy
327
445
 
328
446
    def test_commit_failed_signature(self):
329
 
        import bzrlib.gpg
330
 
        import bzrlib.commit as commit
331
 
        oldstrategy = bzrlib.gpg.GPGStrategy
 
447
        import breezy.gpg
 
448
        import breezy.commit as commit
 
449
        oldstrategy = breezy.gpg.GPGStrategy
332
450
        wt = self.make_branch_and_tree('.')
333
451
        branch = wt.branch
334
 
        wt.commit("base", allow_pointless=True, rev_id='A')
335
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
452
        wt.commit("base", allow_pointless=True, rev_id=b'A')
 
453
        self.assertFalse(branch.repository.has_signature_for_revision_id(b'A'))
336
454
        try:
337
 
            from bzrlib.testament import Testament
338
455
            # monkey patch gpg signing mechanism
339
 
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
340
 
            config = MustSignConfig(branch)
341
 
            self.assertRaises(SigningFailed,
342
 
                              commit.Commit(config=config).commit,
 
456
            breezy.gpg.GPGStrategy = breezy.gpg.DisabledGPGStrategy
 
457
            conf = config.MemoryStack(b'''
 
458
create_signatures=always
 
459
''')
 
460
            self.assertRaises(breezy.gpg.SigningFailed,
 
461
                              commit.Commit(config_stack=conf).commit,
343
462
                              message="base",
344
463
                              allow_pointless=True,
345
 
                              rev_id='B',
 
464
                              rev_id=b'B',
346
465
                              working_tree=wt)
347
466
            branch = Branch.open(self.get_url('.'))
348
 
            self.assertEqual(branch.revision_history(), ['A'])
349
 
            self.failIf(branch.repository.has_revision('B'))
 
467
            self.assertEqual(branch.last_revision(), b'A')
 
468
            self.assertFalse(branch.repository.has_revision(b'B'))
350
469
        finally:
351
 
            bzrlib.gpg.GPGStrategy = oldstrategy
 
470
            breezy.gpg.GPGStrategy = oldstrategy
352
471
 
353
472
    def test_commit_invokes_hooks(self):
354
 
        import bzrlib.commit as commit
 
473
        import breezy.commit as commit
355
474
        wt = self.make_branch_and_tree('.')
356
475
        branch = wt.branch
357
476
        calls = []
358
477
        def called(branch, rev_id):
359
478
            calls.append('called')
360
 
        bzrlib.ahook = called
 
479
        breezy.ahook = called
361
480
        try:
362
 
            config = BranchWithHooks(branch)
363
 
            commit.Commit(config=config).commit(
364
 
                            message = "base",
365
 
                            allow_pointless=True,
366
 
                            rev_id='A', working_tree = wt)
 
481
            conf = config.MemoryStack(b'post_commit=breezy.ahook breezy.ahook')
 
482
            commit.Commit(config_stack=conf).commit(
 
483
                message = "base", allow_pointless=True, rev_id=b'A',
 
484
                working_tree = wt)
367
485
            self.assertEqual(['called', 'called'], calls)
368
486
        finally:
369
 
            del bzrlib.ahook
 
487
            del breezy.ahook
370
488
 
371
489
    def test_commit_object_doesnt_set_nick(self):
372
490
        # using the Commit object directly does not set the branch nick.
373
491
        wt = self.make_branch_and_tree('.')
374
492
        c = Commit()
375
493
        c.commit(working_tree=wt, message='empty tree', allow_pointless=True)
376
 
        self.assertEquals(wt.branch.revno(), 1)
 
494
        self.assertEqual(wt.branch.revno(), 1)
377
495
        self.assertEqual({},
378
496
                         wt.branch.repository.get_revision(
379
497
                            wt.branch.last_revision()).properties)
392
510
            self.assertRaises(LockContention, wt.commit, 'silly')
393
511
        finally:
394
512
            master_branch.unlock()
 
513
 
 
514
    def test_commit_bound_merge(self):
 
515
        # see bug #43959; commit of a merge in a bound branch fails to push
 
516
        # the new commit into the master
 
517
        master_branch = self.make_branch('master')
 
518
        bound_tree = self.make_branch_and_tree('bound')
 
519
        bound_tree.branch.bind(master_branch)
 
520
 
 
521
        self.build_tree_contents([('bound/content_file', b'initial contents\n')])
 
522
        bound_tree.add(['content_file'])
 
523
        bound_tree.commit(message='woo!')
 
524
 
 
525
        other_bzrdir = master_branch.controldir.sprout('other')
 
526
        other_tree = other_bzrdir.open_workingtree()
 
527
 
 
528
        # do a commit to the other branch changing the content file so
 
529
        # that our commit after merging will have a merged revision in the
 
530
        # content file history.
 
531
        self.build_tree_contents([('other/content_file', b'change in other\n')])
 
532
        other_tree.commit('change in other')
 
533
 
 
534
        # do a merge into the bound branch from other, and then change the
 
535
        # content file locally to force a new revision (rather than using the
 
536
        # revision from other). This forces extra processing in commit.
 
537
        bound_tree.merge_from_branch(other_tree.branch)
 
538
        self.build_tree_contents([('bound/content_file', b'change in bound\n')])
 
539
 
 
540
        # before #34959 was fixed, this failed with 'revision not present in
 
541
        # weave' when trying to implicitly push from the bound branch to the master
 
542
        bound_tree.commit(message='commit of merge in bound tree')
 
543
 
 
544
    def test_commit_reporting_after_merge(self):
 
545
        # when doing a commit of a merge, the reporter needs to still
 
546
        # be called for each item that is added/removed/deleted.
 
547
        this_tree = self.make_branch_and_tree('this')
 
548
        # we need a bunch of files and dirs, to perform one action on each.
 
549
        self.build_tree([
 
550
            'this/dirtorename/',
 
551
            'this/dirtoreparent/',
 
552
            'this/dirtoleave/',
 
553
            'this/dirtoremove/',
 
554
            'this/filetoreparent',
 
555
            'this/filetorename',
 
556
            'this/filetomodify',
 
557
            'this/filetoremove',
 
558
            'this/filetoleave']
 
559
            )
 
560
        this_tree.add([
 
561
            'dirtorename',
 
562
            'dirtoreparent',
 
563
            'dirtoleave',
 
564
            'dirtoremove',
 
565
            'filetoreparent',
 
566
            'filetorename',
 
567
            'filetomodify',
 
568
            'filetoremove',
 
569
            'filetoleave']
 
570
            )
 
571
        this_tree.commit('create_files')
 
572
        other_dir = this_tree.controldir.sprout('other')
 
573
        other_tree = other_dir.open_workingtree()
 
574
        other_tree.lock_write()
 
575
        # perform the needed actions on the files and dirs.
 
576
        try:
 
577
            other_tree.rename_one('dirtorename', 'renameddir')
 
578
            other_tree.rename_one('dirtoreparent', 'renameddir/reparenteddir')
 
579
            other_tree.rename_one('filetorename', 'renamedfile')
 
580
            other_tree.rename_one('filetoreparent', 'renameddir/reparentedfile')
 
581
            other_tree.remove(['dirtoremove', 'filetoremove'])
 
582
            self.build_tree_contents([
 
583
                ('other/newdir/', ),
 
584
                ('other/filetomodify', b'new content'),
 
585
                ('other/newfile', b'new file content')])
 
586
            other_tree.add('newfile')
 
587
            other_tree.add('newdir/')
 
588
            other_tree.commit('modify all sample files and dirs.')
 
589
        finally:
 
590
            other_tree.unlock()
 
591
        this_tree.merge_from_branch(other_tree.branch)
 
592
        reporter = CapturingReporter()
 
593
        this_tree.commit('do the commit', reporter=reporter)
 
594
        expected = {
 
595
            ('change', 'modified', 'filetomodify'),
 
596
            ('change', 'added', 'newdir'),
 
597
            ('change', 'added', 'newfile'),
 
598
            ('renamed', 'renamed', 'dirtorename', 'renameddir'),
 
599
            ('renamed', 'renamed', 'filetorename', 'renamedfile'),
 
600
            ('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
 
601
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
 
602
            ('deleted', 'dirtoremove'),
 
603
            ('deleted', 'filetoremove'),
 
604
            }
 
605
        result = set(reporter.calls)
 
606
        missing = expected - result
 
607
        new = result - expected
 
608
        self.assertEqual((set(), set()), (missing, new))
 
609
 
 
610
    def test_commit_removals_respects_filespec(self):
 
611
        """Commit respects the specified_files for removals."""
 
612
        tree = self.make_branch_and_tree('.')
 
613
        self.build_tree(['a', 'b'])
 
614
        tree.add(['a', 'b'])
 
615
        tree.commit('added a, b')
 
616
        tree.remove(['a', 'b'])
 
617
        tree.commit('removed a', specific_files='a')
 
618
        basis = tree.basis_tree()
 
619
        with tree.lock_read():
 
620
            self.assertFalse(basis.is_versioned('a'))
 
621
            self.assertTrue(basis.is_versioned('b'))
 
622
 
 
623
    def test_commit_saves_1ms_timestamp(self):
 
624
        """Passing in a timestamp is saved with 1ms resolution"""
 
625
        tree = self.make_branch_and_tree('.')
 
626
        self.build_tree(['a'])
 
627
        tree.add('a')
 
628
        tree.commit('added a', timestamp=1153248633.4186721, timezone=0,
 
629
                    rev_id=b'a1')
 
630
 
 
631
        rev = tree.branch.repository.get_revision(b'a1')
 
632
        self.assertEqual(1153248633.419, rev.timestamp)
 
633
 
 
634
    def test_commit_has_1ms_resolution(self):
 
635
        """Allowing commit to generate the timestamp also has 1ms resolution"""
 
636
        tree = self.make_branch_and_tree('.')
 
637
        self.build_tree(['a'])
 
638
        tree.add('a')
 
639
        tree.commit('added a', rev_id=b'a1')
 
640
 
 
641
        rev = tree.branch.repository.get_revision(b'a1')
 
642
        timestamp = rev.timestamp
 
643
        timestamp_1ms = round(timestamp, 3)
 
644
        self.assertEqual(timestamp_1ms, timestamp)
 
645
 
 
646
    def assertBasisTreeKind(self, kind, tree, path):
 
647
        basis = tree.basis_tree()
 
648
        basis.lock_read()
 
649
        try:
 
650
            self.assertEqual(kind, basis.kind(path))
 
651
        finally:
 
652
            basis.unlock()
 
653
 
 
654
    def test_commit_kind_changes(self):
 
655
        self.requireFeature(SymlinkFeature)
 
656
        tree = self.make_branch_and_tree('.')
 
657
        os.symlink('target', 'name')
 
658
        tree.add('name', b'a-file-id')
 
659
        tree.commit('Added a symlink')
 
660
        self.assertBasisTreeKind('symlink', tree, 'name')
 
661
 
 
662
        os.unlink('name')
 
663
        self.build_tree(['name'])
 
664
        tree.commit('Changed symlink to file')
 
665
        self.assertBasisTreeKind('file', tree, 'name')
 
666
 
 
667
        os.unlink('name')
 
668
        os.symlink('target', 'name')
 
669
        tree.commit('file to symlink')
 
670
        self.assertBasisTreeKind('symlink', tree, 'name')
 
671
 
 
672
        os.unlink('name')
 
673
        os.mkdir('name')
 
674
        tree.commit('symlink to directory')
 
675
        self.assertBasisTreeKind('directory', tree, 'name')
 
676
 
 
677
        os.rmdir('name')
 
678
        os.symlink('target', 'name')
 
679
        tree.commit('directory to symlink')
 
680
        self.assertBasisTreeKind('symlink', tree, 'name')
 
681
 
 
682
        # prepare for directory <-> file tests
 
683
        os.unlink('name')
 
684
        os.mkdir('name')
 
685
        tree.commit('symlink to directory')
 
686
        self.assertBasisTreeKind('directory', tree, 'name')
 
687
 
 
688
        os.rmdir('name')
 
689
        self.build_tree(['name'])
 
690
        tree.commit('Changed directory to file')
 
691
        self.assertBasisTreeKind('file', tree, 'name')
 
692
 
 
693
        os.unlink('name')
 
694
        os.mkdir('name')
 
695
        tree.commit('file to directory')
 
696
        self.assertBasisTreeKind('directory', tree, 'name')
 
697
 
 
698
    def test_commit_unversioned_specified(self):
 
699
        """Commit should raise if specified files isn't in basis or worktree"""
 
700
        tree = self.make_branch_and_tree('.')
 
701
        self.assertRaises(errors.PathsNotVersionedError, tree.commit,
 
702
                          'message', specific_files=['bogus'])
 
703
 
 
704
    class Callback(object):
 
705
 
 
706
        def __init__(self, message, testcase):
 
707
            self.called = False
 
708
            self.message = message
 
709
            self.testcase = testcase
 
710
 
 
711
        def __call__(self, commit_obj):
 
712
            self.called = True
 
713
            self.testcase.assertTrue(isinstance(commit_obj, Commit))
 
714
            return self.message
 
715
 
 
716
    def test_commit_callback(self):
 
717
        """Commit should invoke a callback to get the message"""
 
718
 
 
719
        tree = self.make_branch_and_tree('.')
 
720
        try:
 
721
            tree.commit()
 
722
        except Exception as e:
 
723
            self.assertTrue(isinstance(e, BzrError))
 
724
            self.assertEqual('The message or message_callback keyword'
 
725
                             ' parameter is required for commit().', str(e))
 
726
        else:
 
727
            self.fail('exception not raised')
 
728
        cb = self.Callback(u'commit 1', self)
 
729
        tree.commit(message_callback=cb)
 
730
        self.assertTrue(cb.called)
 
731
        repository = tree.branch.repository
 
732
        message = repository.get_revision(tree.last_revision()).message
 
733
        self.assertEqual('commit 1', message)
 
734
 
 
735
    def test_no_callback_pointless(self):
 
736
        """Callback should not be invoked for pointless commit"""
 
737
        tree = self.make_branch_and_tree('.')
 
738
        cb = self.Callback(u'commit 2', self)
 
739
        self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
 
740
                          allow_pointless=False)
 
741
        self.assertFalse(cb.called)
 
742
 
 
743
    def test_no_callback_netfailure(self):
 
744
        """Callback should not be invoked if connectivity fails"""
 
745
        tree = self.make_branch_and_tree('.')
 
746
        cb = self.Callback(u'commit 2', self)
 
747
        repository = tree.branch.repository
 
748
        # simulate network failure
 
749
        def raise_(self, arg, arg2, arg3=None, arg4=None):
 
750
            raise errors.NoSuchFile('foo')
 
751
        repository.add_inventory = raise_
 
752
        repository.add_inventory_by_delta = raise_
 
753
        self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
 
754
        self.assertFalse(cb.called)
 
755
 
 
756
    def test_selected_file_merge_commit(self):
 
757
        """Ensure the correct error is raised"""
 
758
        tree = self.make_branch_and_tree('foo')
 
759
        # pending merge would turn into a left parent
 
760
        tree.commit('commit 1')
 
761
        tree.add_parent_tree_id(b'example')
 
762
        self.build_tree(['foo/bar', 'foo/baz'])
 
763
        tree.add(['bar', 'baz'])
 
764
        err = self.assertRaises(CannotCommitSelectedFileMerge,
 
765
            tree.commit, 'commit 2', specific_files=['bar', 'baz'])
 
766
        self.assertEqual(['bar', 'baz'], err.files)
 
767
        self.assertEqual('Selected-file commit of merges is not supported'
 
768
                         ' yet: files bar, baz', str(err))
 
769
 
 
770
    def test_commit_ordering(self):
 
771
        """Test of corner-case commit ordering error"""
 
772
        tree = self.make_branch_and_tree('.')
 
773
        self.build_tree(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
 
774
        tree.add(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
 
775
        tree.commit('setup')
 
776
        self.build_tree(['a/c/d/'])
 
777
        tree.add('a/c/d')
 
778
        tree.rename_one('a/z/x', 'a/c/d/x')
 
779
        tree.commit('test', specific_files=['a/z/y'])
 
780
 
 
781
    def test_commit_no_author(self):
 
782
        """The default kwarg author in MutableTree.commit should not add
 
783
        the 'author' revision property.
 
784
        """
 
785
        tree = self.make_branch_and_tree('foo')
 
786
        rev_id = tree.commit('commit 1')
 
787
        rev = tree.branch.repository.get_revision(rev_id)
 
788
        self.assertFalse('author' in rev.properties)
 
789
        self.assertFalse('authors' in rev.properties)
 
790
 
 
791
    def test_commit_author(self):
 
792
        """Passing a non-empty authors kwarg to MutableTree.commit should add
 
793
        the 'author' revision property.
 
794
        """
 
795
        tree = self.make_branch_and_tree('foo')
 
796
        rev_id = tree.commit(
 
797
            'commit 1',
 
798
            authors=['John Doe <jdoe@example.com>'])
 
799
        rev = tree.branch.repository.get_revision(rev_id)
 
800
        self.assertEqual('John Doe <jdoe@example.com>',
 
801
                         rev.properties['authors'])
 
802
        self.assertFalse('author' in rev.properties)
 
803
 
 
804
    def test_commit_empty_authors_list(self):
 
805
        """Passing an empty list to authors shouldn't add the property."""
 
806
        tree = self.make_branch_and_tree('foo')
 
807
        rev_id = tree.commit('commit 1', authors=[])
 
808
        rev = tree.branch.repository.get_revision(rev_id)
 
809
        self.assertFalse('author' in rev.properties)
 
810
        self.assertFalse('authors' in rev.properties)
 
811
 
 
812
    def test_multiple_authors(self):
 
813
        tree = self.make_branch_and_tree('foo')
 
814
        rev_id = tree.commit('commit 1',
 
815
                authors=['John Doe <jdoe@example.com>',
 
816
                         'Jane Rey <jrey@example.com>'])
 
817
        rev = tree.branch.repository.get_revision(rev_id)
 
818
        self.assertEqual('John Doe <jdoe@example.com>\n'
 
819
                'Jane Rey <jrey@example.com>', rev.properties['authors'])
 
820
        self.assertFalse('author' in rev.properties)
 
821
 
 
822
    def test_author_with_newline_rejected(self):
 
823
        tree = self.make_branch_and_tree('foo')
 
824
        self.assertRaises(AssertionError, tree.commit, 'commit 1',
 
825
                authors=['John\nDoe <jdoe@example.com>'])
 
826
 
 
827
    def test_commit_with_checkout_and_branch_sharing_repo(self):
 
828
        repo = self.make_repository('repo', shared=True)
 
829
        # make_branch_and_tree ignores shared repos
 
830
        branch = controldir.ControlDir.create_branch_convenience('repo/branch')
 
831
        tree2 = branch.create_checkout('repo/tree2')
 
832
        tree2.commit('message', rev_id=b'rev1')
 
833
        self.assertTrue(tree2.branch.repository.has_revision(b'rev1'))
 
834
 
 
835
 
 
836
class FilterExcludedTests(TestCase):
 
837
 
 
838
    def test_add_file_not_excluded(self):
 
839
        changes = [
 
840
            ('fid', (None, 'newpath'),
 
841
             0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
 
842
             ('file', 'file'), (True, True))]
 
843
        self.assertEqual(changes, list(filter_excluded(changes, ['otherpath'])))
 
844
 
 
845
    def test_add_file_excluded(self):
 
846
        changes = [
 
847
            ('fid', (None, 'newpath'),
 
848
             0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
 
849
             ('file', 'file'), (True, True))]
 
850
        self.assertEqual([], list(filter_excluded(changes, ['newpath'])))
 
851
 
 
852
    def test_delete_file_excluded(self):
 
853
        changes = [
 
854
            ('fid', ('somepath', None),
 
855
             0, (False, None), ('pid', None), ('newpath', None),
 
856
             ('file', None), (True, None))]
 
857
        self.assertEqual([], list(filter_excluded(changes, ['somepath'])))
 
858
 
 
859
    def test_move_from_or_to_excluded(self):
 
860
        changes = [
 
861
            ('fid', ('oldpath', 'newpath'),
 
862
             0, (False, False), ('pid', 'pid'), ('oldpath', 'newpath'),
 
863
             ('file', 'file'), (True, True))]
 
864
        self.assertEqual([], list(filter_excluded(changes, ['oldpath'])))
 
865
        self.assertEqual([], list(filter_excluded(changes, ['newpath'])))