/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/plugins/upload/tests/test_upload.py

  • Committer: Jelmer Vernooij
  • Date: 2017-06-02 00:04:01 UTC
  • mfrom: (0.152.95 trunk)
  • mto: This revision was merged to the branch mainline in revision 6649.
  • Revision ID: jelmer@jelmer.uk-20170602000401-lb0559slctqm8bd5
Bundle the upload plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2008-2012 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
 
 
17
import os
 
18
import sys
 
19
 
 
20
 
 
21
from .... import (
 
22
    bzrdir,
 
23
    config,
 
24
    errors,
 
25
    osutils,
 
26
    revisionspec,
 
27
    tests,
 
28
    transport,
 
29
    workingtree,
 
30
    uncommit,
 
31
    )
 
32
from ....tests import (
 
33
    features,
 
34
    per_branch,
 
35
    per_transport,
 
36
    stub_sftp,
 
37
    )
 
38
from ....transport import (
 
39
    ftp,
 
40
    sftp,
 
41
    )
 
42
from .. import (
 
43
    cmds,
 
44
    )
 
45
 
 
46
 
 
47
def get_transport_scenarios():
 
48
    result = []
 
49
    basis = per_transport.transport_test_permutations()
 
50
    # Keep only the interesting ones for upload
 
51
    for name, d in basis:
 
52
        t_class = d['transport_class']
 
53
        if t_class in (ftp.FtpTransport, sftp.SFTPTransport):
 
54
            result.append((name, d))
 
55
    try:
 
56
        import breezy.plugins.local_test_server
 
57
        from breezy.plugins.local_test_server import test_server
 
58
        if False:
 
59
            # XXX: Disable since we can't get chmod working for anonymous
 
60
            # user
 
61
            scenario = ('vsftpd',
 
62
                        {'transport_class': test_server.FtpTransport,
 
63
                         'transport_server': test_server.Vsftpd,
 
64
                         })
 
65
            result.append(scenario)
 
66
        from test_server import ProftpdFeature
 
67
        if ProftpdFeature().available():
 
68
            scenario = ('proftpd',
 
69
                        {'transport_class': test_server.FtpTransport,
 
70
                         'transport_server': test_server.Proftpd,
 
71
                         })
 
72
            result.append(scenario)
 
73
        # XXX: add support for pyftpdlib
 
74
    except ImportError:
 
75
        pass
 
76
    return result
 
77
 
 
78
 
 
79
def load_tests(loader, standard_tests, pattern):
 
80
    """Multiply tests for tranport implementations."""
 
81
    result = loader.suiteClass()
 
82
 
 
83
    # one for each transport implementation
 
84
    t_tests, remaining_tests = tests.split_suite_by_condition(
 
85
        standard_tests, tests.condition_isinstance((
 
86
                TestFullUpload,
 
87
                TestIncrementalUpload,
 
88
                TestUploadFromRemoteBranch,
 
89
                )))
 
90
    tests.multiply_tests(t_tests, get_transport_scenarios(), result)
 
91
 
 
92
    # one for each branch format
 
93
    b_tests, remaining_tests = tests.split_suite_by_condition(
 
94
        remaining_tests, tests.condition_isinstance((
 
95
                TestBranchUploadLocations,
 
96
                )))
 
97
    tests.multiply_tests(b_tests, per_branch.branch_scenarios(),
 
98
                         result)
 
99
 
 
100
    # No parametrization for the remaining tests
 
101
    result.addTests(remaining_tests)
 
102
 
 
103
    return result
 
104
 
 
105
 
 
106
class UploadUtilsMixin(object):
 
107
    """Helper class to write upload tests.
 
108
 
 
109
    This class provides helpers to simplify test writing. The emphasis is on
 
110
    easy test writing, so each tree modification is committed. This doesn't
 
111
    preclude writing tests spawning several revisions to upload more complex
 
112
    changes.
 
113
    """
 
114
 
 
115
    upload_dir = 'upload'
 
116
    branch_dir = 'branch'
 
117
 
 
118
    def make_branch_and_working_tree(self):
 
119
        t = transport.get_transport(self.branch_dir)
 
120
        t.ensure_base()
 
121
        branch = bzrdir.BzrDir.create_branch_convenience(
 
122
            t.base,
 
123
            format=bzrdir.format_registry.make_bzrdir('default'),
 
124
            force_new_tree=False)
 
125
        self.tree = branch.bzrdir.create_workingtree()
 
126
        self.tree.commit('initial empty tree')
 
127
 
 
128
    def assertUpFileEqual(self, content, path, base=upload_dir):
 
129
        self.assertFileEqual(content, osutils.pathjoin(base, path))
 
130
 
 
131
    def assertUpPathModeEqual(self, path, expected_mode, base=upload_dir):
 
132
        # FIXME: the tests needing that assertion should depend on the server
 
133
        # ability to handle chmod so that they don't fail (or be skipped)
 
134
        # against servers that can't. Note that some breezy transports define
 
135
        # _can_roundtrip_unix_modebits in a incomplete way, this property
 
136
        # should depend on both the client and the server, not the client only.
 
137
        # But the client will know or can find if the server support chmod so
 
138
        # that's the client that will report it anyway.
 
139
        full_path = osutils.pathjoin(base, path)
 
140
        st = os.stat(full_path)
 
141
        mode = st.st_mode & 0777
 
142
        if expected_mode == mode:
 
143
            return
 
144
        raise AssertionError(
 
145
            'For path %s, mode is %s not %s' %
 
146
            (full_path, oct(mode), oct(expected_mode)))
 
147
 
 
148
    def assertUpPathDoesNotExist(self, path, base=upload_dir):
 
149
        self.assertPathDoesNotExist(osutils.pathjoin(base, path))
 
150
 
 
151
    def assertUpPathExists(self, path, base=upload_dir):
 
152
        self.assertPathExists(osutils.pathjoin(base, path))
 
153
 
 
154
    def set_file_content(self, path, content, base=branch_dir):
 
155
        f = file(osutils.pathjoin(base, path), 'wb')
 
156
        try:
 
157
            f.write(content)
 
158
        finally:
 
159
            f.close()
 
160
 
 
161
    def add_file(self, path, content, base=branch_dir):
 
162
        self.set_file_content(path, content, base)
 
163
        self.tree.add(path)
 
164
        self.tree.commit('add file %s' % path)
 
165
 
 
166
    def modify_file(self, path, content, base=branch_dir):
 
167
        self.set_file_content(path, content, base)
 
168
        self.tree.commit('modify file %s' % path)
 
169
 
 
170
    def chmod_file(self, path, mode, base=branch_dir):
 
171
        full_path = osutils.pathjoin(base, path)
 
172
        os.chmod(full_path, mode)
 
173
        self.tree.commit('change file %s mode to %s' % (path, oct(mode)))
 
174
 
 
175
    def delete_any(self, path, base=branch_dir):
 
176
        self.tree.remove([path], keep_files=False)
 
177
        self.tree.commit('delete %s' % path)
 
178
 
 
179
    def add_dir(self, path, base=branch_dir):
 
180
        os.mkdir(osutils.pathjoin(base, path))
 
181
        self.tree.add(path)
 
182
        self.tree.commit('add directory %s' % path)
 
183
 
 
184
    def rename_any(self, old_path, new_path):
 
185
        self.tree.rename_one(old_path, new_path)
 
186
        self.tree.commit('rename %s into %s' % (old_path, new_path))
 
187
 
 
188
    def transform_dir_into_file(self, path, content, base=branch_dir):
 
189
        osutils.delete_any(osutils.pathjoin(base, path))
 
190
        self.set_file_content(path, content, base)
 
191
        self.tree.commit('change %s from dir to file' % path)
 
192
 
 
193
    def transform_file_into_dir(self, path, base=branch_dir):
 
194
        # bzr can't handle that kind change in a single commit without an
 
195
        # intervening bzr status (see bug #205636).
 
196
        self.tree.remove([path], keep_files=False)
 
197
        os.mkdir(osutils.pathjoin(base, path))
 
198
        self.tree.add(path)
 
199
        self.tree.commit('change %s from file to dir' % path)
 
200
 
 
201
    def add_symlink(self, path, target, base=branch_dir):
 
202
        self.requireFeature(features.SymlinkFeature)
 
203
        os.symlink(target, osutils.pathjoin(base, path))
 
204
        self.tree.add(path)
 
205
        self.tree.commit('add symlink %s -> %s' % (path, target))
 
206
 
 
207
    def modify_symlink(self, path, target, base=branch_dir):
 
208
        self.requireFeature(features.SymlinkFeature)
 
209
        full_path = osutils.pathjoin(base, path)
 
210
        os.unlink(full_path)
 
211
        os.symlink(target, full_path)
 
212
        self.tree.commit('modify symlink %s -> %s' % (path, target))
 
213
 
 
214
    def _get_cmd_upload(self):
 
215
        cmd = cmds.cmd_upload()
 
216
        # We don't want to use run_bzr here because redirected output are a
 
217
        # pain to debug. But we need to provides a valid outf.
 
218
        # XXX: Should a bug against bzr be filled about that ?
 
219
 
 
220
        # Short story: we don't expect any output so we may just use stdout
 
221
        cmd.outf = sys.stdout
 
222
        return cmd
 
223
 
 
224
    def do_full_upload(self, *args, **kwargs):
 
225
        upload = self._get_cmd_upload()
 
226
        up_url = self.get_url(self.upload_dir)
 
227
        if kwargs.get('directory', None) is None:
 
228
            kwargs['directory'] = self.branch_dir
 
229
        kwargs['full'] = True
 
230
        kwargs['quiet'] = True
 
231
        upload.run(up_url, *args, **kwargs)
 
232
 
 
233
    def do_incremental_upload(self, *args, **kwargs):
 
234
        upload = self._get_cmd_upload()
 
235
        up_url = self.get_url(self.upload_dir)
 
236
        if kwargs.get('directory', None) is None:
 
237
            kwargs['directory'] = self.branch_dir
 
238
        kwargs['quiet'] = True
 
239
        upload.run(up_url, *args, **kwargs)
 
240
 
 
241
 
 
242
class TestUploadMixin(UploadUtilsMixin):
 
243
    """Helper class to share tests between full and incremental uploads."""
 
244
 
 
245
    def _test_create_file(self, file_name):
 
246
        self.make_branch_and_working_tree()
 
247
        self.do_full_upload()
 
248
        self.add_file(file_name, 'foo')
 
249
 
 
250
        self.do_upload()
 
251
 
 
252
        self.assertUpFileEqual('foo', file_name)
 
253
 
 
254
    def test_create_file(self):
 
255
        self._test_create_file('hello')
 
256
 
 
257
    def test_unicode_create_file(self):
 
258
        self.requireFeature(features.UnicodeFilenameFeature)
 
259
        self._test_create_file(u'hell\u00d8')
 
260
 
 
261
    def _test_create_file_in_dir(self, dir_name, file_name):
 
262
        self.make_branch_and_working_tree()
 
263
        self.do_full_upload()
 
264
        self.add_dir(dir_name)
 
265
        fpath = '%s/%s' % (dir_name, file_name)
 
266
        self.add_file(fpath, 'baz')
 
267
 
 
268
        self.assertUpPathDoesNotExist(fpath)
 
269
 
 
270
        self.do_upload()
 
271
 
 
272
        self.assertUpFileEqual('baz', fpath)
 
273
        self.assertUpPathModeEqual(dir_name, 0775)
 
274
 
 
275
    def test_create_file_in_dir(self):
 
276
        self._test_create_file_in_dir('dir', 'goodbye')
 
277
 
 
278
    def test_unicode_create_file_in_dir(self):
 
279
        self.requireFeature(features.UnicodeFilenameFeature)
 
280
        self._test_create_file_in_dir(u'dir\u00d8', u'goodbye\u00d8')
 
281
 
 
282
    def test_modify_file(self):
 
283
        self.make_branch_and_working_tree()
 
284
        self.add_file('hello', 'foo')
 
285
        self.do_full_upload()
 
286
        self.modify_file('hello', 'bar')
 
287
 
 
288
        self.assertUpFileEqual('foo', 'hello')
 
289
 
 
290
        self.do_upload()
 
291
 
 
292
        self.assertUpFileEqual('bar', 'hello')
 
293
 
 
294
    def _test_rename_one_file(self, old_name, new_name):
 
295
        self.make_branch_and_working_tree()
 
296
        self.add_file(old_name, 'foo')
 
297
        self.do_full_upload()
 
298
        self.rename_any(old_name, new_name)
 
299
 
 
300
        self.assertUpFileEqual('foo', old_name)
 
301
 
 
302
        self.do_upload()
 
303
 
 
304
        self.assertUpFileEqual('foo', new_name)
 
305
 
 
306
    def test_rename_one_file(self):
 
307
        self._test_rename_one_file('hello', 'goodbye')
 
308
 
 
309
    def test_unicode_rename_one_file(self):
 
310
        self.requireFeature(features.UnicodeFilenameFeature)
 
311
        self._test_rename_one_file(u'hello\u00d8', u'goodbye\u00d8')
 
312
 
 
313
    def test_rename_and_change_file(self):
 
314
        self.make_branch_and_working_tree()
 
315
        self.add_file('hello', 'foo')
 
316
        self.do_full_upload()
 
317
        self.rename_any('hello', 'goodbye')
 
318
        self.modify_file('goodbye', 'bar')
 
319
 
 
320
        self.assertUpFileEqual('foo', 'hello')
 
321
 
 
322
        self.do_upload()
 
323
 
 
324
        self.assertUpFileEqual('bar', 'goodbye')
 
325
 
 
326
    def test_rename_two_files(self):
 
327
        self.make_branch_and_working_tree()
 
328
        self.add_file('a', 'foo')
 
329
        self.add_file('b', 'qux')
 
330
        self.do_full_upload()
 
331
        # We rely on the assumption that bzr will topologically sort the
 
332
        # renames which will cause a -> b to appear *before* b -> c
 
333
        self.rename_any('b', 'c')
 
334
        self.rename_any('a', 'b')
 
335
 
 
336
        self.assertUpFileEqual('foo', 'a')
 
337
        self.assertUpFileEqual('qux', 'b')
 
338
 
 
339
        self.do_upload()
 
340
 
 
341
        self.assertUpFileEqual('foo', 'b')
 
342
        self.assertUpFileEqual('qux', 'c')
 
343
 
 
344
    def test_upload_revision(self):
 
345
        self.make_branch_and_working_tree() # rev1
 
346
        self.do_full_upload()
 
347
        self.add_file('hello', 'foo') # rev2
 
348
        self.modify_file('hello', 'bar') # rev3
 
349
 
 
350
        self.assertUpPathDoesNotExist('hello')
 
351
 
 
352
        revspec = revisionspec.RevisionSpec.from_string('2')
 
353
        self.do_upload(revision=[revspec])
 
354
 
 
355
        self.assertUpFileEqual('foo', 'hello')
 
356
 
 
357
    def test_no_upload_when_changes(self):
 
358
        self.make_branch_and_working_tree()
 
359
        self.add_file('a', 'foo')
 
360
        self.set_file_content('a', 'bar')
 
361
 
 
362
        self.assertRaises(errors.UncommittedChanges, self.do_upload)
 
363
 
 
364
    def test_no_upload_when_conflicts(self):
 
365
        self.make_branch_and_working_tree()
 
366
        self.add_file('a', 'foo')
 
367
        self.run_bzr('branch branch other')
 
368
        self.modify_file('a', 'bar')
 
369
        other_tree = workingtree.WorkingTree.open('other')
 
370
        self.set_file_content('a', 'baz', 'other/')
 
371
        other_tree.commit('modify file a')
 
372
 
 
373
        self.run_bzr('merge -d branch other', retcode=1)
 
374
 
 
375
        self.assertRaises(errors.UncommittedChanges, self.do_upload)
 
376
 
 
377
    def _test_change_file_into_dir(self, file_name):
 
378
        self.make_branch_and_working_tree()
 
379
        self.add_file(file_name, 'foo')
 
380
        self.do_full_upload()
 
381
        self.transform_file_into_dir(file_name)
 
382
        fpath = '%s/%s' % (file_name, 'file')
 
383
        self.add_file(fpath, 'bar')
 
384
 
 
385
        self.assertUpFileEqual('foo', file_name)
 
386
 
 
387
        self.do_upload()
 
388
 
 
389
        self.assertUpFileEqual('bar', fpath)
 
390
 
 
391
    def test_change_file_into_dir(self):
 
392
        self._test_change_file_into_dir('hello')
 
393
 
 
394
    def test_unicode_change_file_into_dir(self):
 
395
        self.requireFeature(features.UnicodeFilenameFeature)
 
396
        self._test_change_file_into_dir(u'hello\u00d8')
 
397
 
 
398
    def test_change_dir_into_file(self):
 
399
        self.make_branch_and_working_tree()
 
400
        self.add_dir('hello')
 
401
        self.add_file('hello/file', 'foo')
 
402
        self.do_full_upload()
 
403
        self.delete_any('hello/file')
 
404
        self.transform_dir_into_file('hello', 'bar')
 
405
 
 
406
        self.assertUpFileEqual('foo', 'hello/file')
 
407
 
 
408
        self.do_upload()
 
409
 
 
410
        self.assertUpFileEqual('bar', 'hello')
 
411
 
 
412
    def _test_make_file_executable(self, file_name):
 
413
        self.make_branch_and_working_tree()
 
414
        self.add_file(file_name, 'foo')
 
415
        self.chmod_file(file_name, 0664)
 
416
        self.do_full_upload()
 
417
        self.chmod_file(file_name, 0755)
 
418
 
 
419
        self.assertUpPathModeEqual(file_name, 0664)
 
420
 
 
421
        self.do_upload()
 
422
 
 
423
        self.assertUpPathModeEqual(file_name, 0775)
 
424
 
 
425
    def test_make_file_executable(self):
 
426
        self._test_make_file_executable('hello')
 
427
 
 
428
    def test_unicode_make_file_executable(self):
 
429
        self.requireFeature(features.UnicodeFilenameFeature)
 
430
        self._test_make_file_executable(u'hello\u00d8')
 
431
 
 
432
    def test_create_symlink(self):
 
433
        self.make_branch_and_working_tree()
 
434
        self.do_full_upload()
 
435
        self.add_symlink('link', 'target')
 
436
 
 
437
        self.do_upload()
 
438
 
 
439
        self.assertUpPathDoesNotExist('link')
 
440
 
 
441
    def test_rename_symlink(self):
 
442
        self.make_branch_and_working_tree()
 
443
        old_name, new_name = 'old-link', 'new-link'
 
444
        self.add_symlink(old_name, 'target')
 
445
        self.do_full_upload()
 
446
        self.rename_any(old_name, new_name)
 
447
 
 
448
        self.do_upload()
 
449
 
 
450
        self.assertUpPathDoesNotExist(old_name)
 
451
        self.assertUpPathDoesNotExist(new_name)
 
452
 
 
453
    def get_upload_auto(self):
 
454
        # We need a fresh branch to check what has been saved on disk
 
455
        b = bzrdir.BzrDir.open(self.tree.basedir).open_branch()
 
456
        return b.get_config_stack().get('upload_auto')
 
457
 
 
458
    def test_upload_auto(self):
 
459
        """Test that upload --auto sets the upload_auto option"""
 
460
        self.make_branch_and_working_tree()
 
461
 
 
462
        self.add_file('hello', 'foo')
 
463
        self.assertFalse(self.get_upload_auto())
 
464
        self.do_full_upload(auto=True)
 
465
        self.assertUpFileEqual('foo', 'hello')
 
466
        self.assertTrue(self.get_upload_auto())
 
467
 
 
468
        # and check that it stays set until it is unset
 
469
        self.add_file('bye', 'bar')
 
470
        self.do_full_upload()
 
471
        self.assertUpFileEqual('bar', 'bye')
 
472
        self.assertTrue(self.get_upload_auto())
 
473
 
 
474
    def test_upload_noauto(self):
 
475
        """Test that upload --no-auto unsets the upload_auto option"""
 
476
        self.make_branch_and_working_tree()
 
477
 
 
478
        self.add_file('hello', 'foo')
 
479
        self.do_full_upload(auto=True)
 
480
        self.assertUpFileEqual('foo', 'hello')
 
481
        self.assertTrue(self.get_upload_auto())
 
482
 
 
483
        self.add_file('bye', 'bar')
 
484
        self.do_full_upload(auto=False)
 
485
        self.assertUpFileEqual('bar', 'bye')
 
486
        self.assertFalse(self.get_upload_auto())
 
487
 
 
488
        # and check that it stays unset until it is set
 
489
        self.add_file('again', 'baz')
 
490
        self.do_full_upload()
 
491
        self.assertUpFileEqual('baz', 'again')
 
492
        self.assertFalse(self.get_upload_auto())
 
493
 
 
494
    def test_upload_from_subdir(self):
 
495
        self.make_branch_and_working_tree()
 
496
        self.build_tree(['branch/foo/', 'branch/foo/bar'])
 
497
        self.tree.add(['foo/', 'foo/bar'])
 
498
        self.tree.commit("Add directory")
 
499
        self.do_full_upload(directory='branch/foo')
 
500
 
 
501
    def test_upload_revid_path_in_dir(self):
 
502
        self.make_branch_and_working_tree()
 
503
        self.add_dir('dir')
 
504
        self.add_file('dir/goodbye', 'baz')
 
505
 
 
506
        revid_path = 'dir/revid-path'
 
507
        self.tree.branch.get_config_stack(
 
508
            ).set('upload_revid_location', revid_path)
 
509
        self.assertUpPathDoesNotExist(revid_path)
 
510
 
 
511
        self.do_full_upload()
 
512
 
 
513
        self.add_file('dir/hello', 'foo')
 
514
 
 
515
        self.do_upload()
 
516
 
 
517
        self.assertUpPathExists(revid_path)
 
518
        self.assertUpFileEqual('baz', 'dir/goodbye')
 
519
        self.assertUpFileEqual('foo', 'dir/hello')
 
520
 
 
521
    def test_ignore_file(self):
 
522
        self.make_branch_and_working_tree()
 
523
        self.do_full_upload()
 
524
        self.add_file('.bzrignore-upload', 'foo')
 
525
        self.add_file('foo', 'bar')
 
526
 
 
527
        self.do_upload()
 
528
 
 
529
        self.assertUpPathDoesNotExist('foo')
 
530
 
 
531
    def test_ignore_regexp(self):
 
532
        self.make_branch_and_working_tree()
 
533
        self.do_full_upload()
 
534
        self.add_file('.bzrignore-upload', 'f*')
 
535
        self.add_file('foo', 'bar')
 
536
 
 
537
        self.do_upload()
 
538
 
 
539
        self.assertUpPathDoesNotExist('foo')
 
540
 
 
541
    def test_ignore_directory(self):
 
542
        self.make_branch_and_working_tree()
 
543
        self.do_full_upload()
 
544
        self.add_file('.bzrignore-upload', 'dir')
 
545
        self.add_dir('dir')
 
546
 
 
547
        self.do_upload()
 
548
 
 
549
        self.assertUpPathDoesNotExist('dir')
 
550
 
 
551
    def test_ignore_nested_directory(self):
 
552
        self.make_branch_and_working_tree()
 
553
        self.do_full_upload()
 
554
        self.add_file('.bzrignore-upload', 'dir')
 
555
        self.add_dir('dir')
 
556
        self.add_dir('dir/foo')
 
557
        self.add_file('dir/foo/bar', 'bar contents')
 
558
 
 
559
        self.do_upload()
 
560
 
 
561
        self.assertUpPathDoesNotExist('dir')
 
562
        self.assertUpPathDoesNotExist('dir/foo/bar')
 
563
 
 
564
    def test_ignore_change_file_into_dir(self):
 
565
        self.make_branch_and_working_tree()
 
566
        self.add_file('hello', 'foo')
 
567
        self.do_full_upload()
 
568
        self.add_file('.bzrignore-upload', 'hello')
 
569
        self.transform_file_into_dir('hello')
 
570
        self.add_file('hello/file', 'bar')
 
571
 
 
572
        self.assertUpFileEqual('foo', 'hello')
 
573
 
 
574
        self.do_upload()
 
575
 
 
576
        self.assertUpFileEqual('foo', 'hello')
 
577
 
 
578
    def test_ignore_change_dir_into_file(self):
 
579
        self.make_branch_and_working_tree()
 
580
        self.add_dir('hello')
 
581
        self.add_file('hello/file', 'foo')
 
582
        self.do_full_upload()
 
583
 
 
584
        self.add_file('.bzrignore-upload', 'hello')
 
585
        self.delete_any('hello/file')
 
586
        self.transform_dir_into_file('hello', 'bar')
 
587
 
 
588
        self.assertUpFileEqual('foo', 'hello/file')
 
589
 
 
590
        self.do_upload()
 
591
 
 
592
        self.assertUpFileEqual('foo', 'hello/file')
 
593
 
 
594
    def test_ignore_delete_dir_in_subdir(self):
 
595
        self.make_branch_and_working_tree()
 
596
        self.add_dir('dir')
 
597
        self.add_dir('dir/subdir')
 
598
        self.add_file('dir/subdir/a', 'foo')
 
599
        self.do_full_upload()
 
600
        self.add_file('.bzrignore-upload', 'dir/subdir')
 
601
        self.rename_any('dir/subdir/a', 'dir/a')
 
602
        self.delete_any('dir/subdir')
 
603
 
 
604
        self.assertUpFileEqual('foo', 'dir/subdir/a')
 
605
 
 
606
        self.do_upload()
 
607
 
 
608
        # The file in the dir is not ignored. This a bit contrived but
 
609
        # indicates that we may encounter problems when ignored items appear
 
610
        # and disappear... -- vila 100106
 
611
        self.assertUpFileEqual('foo', 'dir/a')
 
612
 
 
613
 
 
614
class TestFullUpload(tests.TestCaseWithTransport, TestUploadMixin):
 
615
 
 
616
    do_upload = TestUploadMixin.do_full_upload
 
617
 
 
618
    def test_full_upload_empty_tree(self):
 
619
        self.make_branch_and_working_tree()
 
620
 
 
621
        self.do_full_upload()
 
622
 
 
623
        revid_path = self.tree.branch.get_config_stack(
 
624
            ).get('upload_revid_location')
 
625
        self.assertUpPathExists(revid_path)
 
626
 
 
627
    def test_invalid_revspec(self):
 
628
        self.make_branch_and_working_tree()
 
629
        rev1 = revisionspec.RevisionSpec.from_string('1')
 
630
        rev2 = revisionspec.RevisionSpec.from_string('2')
 
631
 
 
632
        self.assertRaises(errors.BzrCommandError,
 
633
                          self.do_incremental_upload, revision=[rev1, rev2])
 
634
 
 
635
    def test_create_remote_dir_twice(self):
 
636
        self.make_branch_and_working_tree()
 
637
        self.add_dir('dir')
 
638
        self.do_full_upload()
 
639
        self.add_file('dir/goodbye', 'baz')
 
640
 
 
641
        self.assertUpPathDoesNotExist('dir/goodbye')
 
642
 
 
643
        self.do_full_upload()
 
644
 
 
645
        self.assertUpFileEqual('baz', 'dir/goodbye')
 
646
        self.assertUpPathModeEqual('dir', 0775)
 
647
 
 
648
 
 
649
class TestIncrementalUpload(tests.TestCaseWithTransport, TestUploadMixin):
 
650
 
 
651
    do_upload = TestUploadMixin.do_incremental_upload
 
652
 
 
653
    # XXX: full upload doesn't handle deletions....
 
654
 
 
655
    def test_delete_one_file(self):
 
656
        self.make_branch_and_working_tree()
 
657
        self.add_file('hello', 'foo')
 
658
        self.do_full_upload()
 
659
        self.delete_any('hello')
 
660
 
 
661
        self.assertUpFileEqual('foo', 'hello')
 
662
 
 
663
        self.do_upload()
 
664
 
 
665
        self.assertUpPathDoesNotExist('hello')
 
666
 
 
667
    def test_delete_dir_and_subdir(self):
 
668
        self.make_branch_and_working_tree()
 
669
        self.add_dir('dir')
 
670
        self.add_dir('dir/subdir')
 
671
        self.add_file('dir/subdir/a', 'foo')
 
672
        self.do_full_upload()
 
673
        self.rename_any('dir/subdir/a', 'a')
 
674
        self.delete_any('dir/subdir')
 
675
        self.delete_any('dir')
 
676
 
 
677
        self.assertUpFileEqual('foo', 'dir/subdir/a')
 
678
 
 
679
        self.do_upload()
 
680
 
 
681
        self.assertUpPathDoesNotExist('dir/subdir/a')
 
682
        self.assertUpPathDoesNotExist('dir/subdir')
 
683
        self.assertUpPathDoesNotExist('dir')
 
684
        self.assertUpFileEqual('foo', 'a')
 
685
 
 
686
    def test_delete_one_file_rename_to_deleted(self):
 
687
        self.make_branch_and_working_tree()
 
688
        self.add_file('a', 'foo')
 
689
        self.add_file('b', 'bar')
 
690
        self.do_full_upload()
 
691
        self.delete_any('a')
 
692
        self.rename_any('b', 'a')
 
693
 
 
694
        self.assertUpFileEqual('foo', 'a')
 
695
 
 
696
        self.do_upload()
 
697
 
 
698
        self.assertUpPathDoesNotExist('b')
 
699
        self.assertUpFileEqual('bar', 'a')
 
700
 
 
701
    def test_rename_outside_dir_delete_dir(self):
 
702
        self.make_branch_and_working_tree()
 
703
        self.add_dir('dir')
 
704
        self.add_file('dir/a', 'foo')
 
705
        self.do_full_upload()
 
706
        self.rename_any('dir/a', 'a')
 
707
        self.delete_any('dir')
 
708
 
 
709
        self.assertUpFileEqual('foo', 'dir/a')
 
710
 
 
711
        self.do_upload()
 
712
 
 
713
        self.assertUpPathDoesNotExist('dir/a')
 
714
        self.assertUpPathDoesNotExist('dir')
 
715
        self.assertUpFileEqual('foo', 'a')
 
716
 
 
717
    def test_delete_symlink(self):
 
718
        self.make_branch_and_working_tree()
 
719
        self.add_symlink('link', 'target')
 
720
        self.do_full_upload()
 
721
        self.delete_any('link')
 
722
 
 
723
        self.do_upload()
 
724
 
 
725
        self.assertUpPathDoesNotExist('link')
 
726
 
 
727
    def test_upload_for_the_first_time_do_a_full_upload(self):
 
728
        self.make_branch_and_working_tree()
 
729
        self.add_file('hello', 'bar')
 
730
 
 
731
        revid_path = self.tree.branch.get_config_stack(
 
732
            ).get('upload_revid_location')
 
733
        self.assertUpPathDoesNotExist(revid_path)
 
734
 
 
735
        self.do_upload()
 
736
 
 
737
        self.assertUpFileEqual('bar', 'hello')
 
738
 
 
739
    def test_ignore_delete_one_file(self):
 
740
        self.make_branch_and_working_tree()
 
741
        self.add_file('hello', 'foo')
 
742
        self.do_full_upload()
 
743
        self.add_file('.bzrignore-upload', 'hello')
 
744
        self.delete_any('hello')
 
745
 
 
746
        self.assertUpFileEqual('foo', 'hello')
 
747
 
 
748
        self.do_upload()
 
749
 
 
750
        self.assertUpFileEqual('foo', 'hello')
 
751
 
 
752
 
 
753
class TestBranchUploadLocations(per_branch.TestCaseWithBranch):
 
754
 
 
755
    def test_get_upload_location_unset(self):
 
756
        conf = self.get_branch().get_config_stack()
 
757
        self.assertEqual(None, conf.get('upload_location'))
 
758
 
 
759
    def test_get_push_location_exact(self):
 
760
        config.ensure_config_dir_exists()
 
761
        fn = config.locations_config_filename()
 
762
        b = self.get_branch()
 
763
        with open(fn, 'wt') as f:
 
764
            f.write(("[%s]\n" "upload_location=foo\n" % b.base.rstrip("/")))
 
765
        self.assertEqual("foo", b.get_config_stack().get('upload_location'))
 
766
 
 
767
    def test_set_push_location(self):
 
768
        conf = self.get_branch().get_config_stack()
 
769
        conf.set('upload_location', 'foo')
 
770
        self.assertEqual('foo', conf.get('upload_location'))
 
771
 
 
772
 
 
773
class TestUploadFromRemoteBranch(tests.TestCaseWithTransport, UploadUtilsMixin):
 
774
 
 
775
    remote_branch_dir = 'remote_branch'
 
776
 
 
777
    def setUp(self):
 
778
        super(TestUploadFromRemoteBranch, self).setUp()
 
779
        self.remote_branch_url = self.make_remote_branch_without_working_tree()
 
780
 
 
781
    def make_remote_branch_without_working_tree(self):
 
782
        """Creates a branch without working tree to upload from.
 
783
 
 
784
        It's created from the existing self.branch_dir one which still has its
 
785
        working tree.
 
786
        """
 
787
        self.make_branch_and_working_tree()
 
788
        self.add_file('hello', 'foo')
 
789
 
 
790
        remote_branch_url = self.get_url(self.remote_branch_dir)
 
791
        if self.transport_server is stub_sftp.SFTPHomeDirServer:
 
792
            # FIXME: Some policy search ends up above the user home directory
 
793
            # and are seen as attemps to escape test isolation
 
794
            raise tests.TestNotApplicable('Escaping test isolation')
 
795
        self.run_bzr(['push', remote_branch_url,
 
796
                      '--directory', self.branch_dir])
 
797
        return remote_branch_url
 
798
 
 
799
    def test_no_upload_to_remote_working_tree(self):
 
800
        cmd = self._get_cmd_upload()
 
801
        up_url = self.get_url(self.branch_dir)
 
802
        # Let's try to upload from the just created remote branch into the
 
803
        # branch (which has a working tree).
 
804
        self.assertRaises(cmds.CannotUploadToWorkingTree,
 
805
                          cmd.run, up_url, directory=self.remote_branch_url)
 
806
 
 
807
    def test_upload_without_working_tree(self):
 
808
        self.do_full_upload(directory=self.remote_branch_url)
 
809
        self.assertUpFileEqual('foo', 'hello')
 
810
 
 
811
 
 
812
class TestUploadDiverged(tests.TestCaseWithTransport, UploadUtilsMixin):
 
813
 
 
814
    def setUp(self):
 
815
        super(TestUploadDiverged, self).setUp()
 
816
        self.diverged_tree = self.make_diverged_tree_and_upload_location()
 
817
 
 
818
    def make_diverged_tree_and_upload_location(self):
 
819
        tree_a = self.make_branch_and_tree('tree_a')
 
820
        tree_a.commit('message 1', rev_id='rev1')
 
821
        tree_a.commit('message 2', rev_id='rev2a')
 
822
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
 
823
        uncommit.uncommit(tree_b.branch, tree=tree_b)
 
824
        tree_b.commit('message 2', rev_id='rev2b')
 
825
        # upload tree a
 
826
        self.do_full_upload(directory=tree_a.basedir)
 
827
        return tree_b
 
828
 
 
829
    def assertRevidUploaded(self, revid):
 
830
        t = self.get_transport(self.upload_dir)
 
831
        uploaded_revid = t.get_bytes('.bzr-upload.revid')
 
832
        self.assertEqual(revid, uploaded_revid)
 
833
 
 
834
    def test_cant_upload_diverged(self):
 
835
        self.assertRaises(cmds.DivergedUploadedTree,
 
836
                          self.do_incremental_upload,
 
837
                          directory=self.diverged_tree.basedir)
 
838
        self.assertRevidUploaded('rev2a')
 
839
 
 
840
    def test_upload_diverged_with_overwrite(self):
 
841
        self.do_incremental_upload(directory=self.diverged_tree.basedir,
 
842
                                   overwrite=True)
 
843
        self.assertRevidUploaded('rev2b')
 
844
 
 
845
 
 
846
class TestUploadBadRemoteReivd(tests.TestCaseWithTransport, UploadUtilsMixin):
 
847
 
 
848
    def test_raises_on_wrong_revid(self):
 
849
        tree = self.make_branch_and_working_tree()
 
850
        self.do_full_upload()
 
851
        # Put a fake revid on the remote branch
 
852
        t = self.get_transport(self.upload_dir)
 
853
        t.put_bytes('.bzr-upload.revid', 'fake')
 
854
        # Make a change
 
855
        self.add_file('foo', 'bar\n')
 
856
        self.assertRaises(cmds.DivergedUploadedTree, self.do_full_upload)
 
857