Rev 44: More robust full upload (at least regarding files changed to dirs and vice-versa). in http://bazaar.launchpad.net/%7Ebzr-upload-devs/bzr-upload/trunk
Vincent Ladeuil
v.ladeuil+lp at free.fr
Thu Jun 19 17:09:31 BST 2008
At http://bazaar.launchpad.net/%7Ebzr-upload-devs/bzr-upload/trunk
------------------------------------------------------------
revno: 44
revision-id: v.ladeuil+lp at free.fr-20080619160902-estp23h3nlv70gqh
parent: v.ladeuil+lp at free.fr-20080610072348-bfpw2e9upjf1afdw
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: upload
timestamp: Thu 2008-06-19 18:09:02 +0200
message:
More robust full upload (at least regarding files changed to dirs and vice-versa).
* tests/test_upload.py:
(TestUploadMixin.transform_file_into_dir): Work around bzrlib
limitation by doing a remove/add when a file is changed into a
dir (we may reconsider when bug #205636 is fixed ;-).
(TestUploadMixin.test_change_file_into_dir,
TestUploadMixin.test_change_dir_into_file): Moved from
TestIncrementalUpload since full upload can now handle the cases.
* __init__.py:
(cmd_upload.upload_file_robustly,
cmd_upload.make_remote_dir_robustly): New methods.
(cmd_upload.upload_full_tree): Use more robust methods.
modified:
__init__.py __init__.py-20080307145942-xx1xgifrreovahgz-1
tests/test_upload.py test_upload.py-20080307145942-xx1xgifrreovahgz-2
-------------- next part --------------
=== modified file '__init__.py'
--- a/__init__.py 2008-06-10 07:23:48 +0000
+++ b/__init__.py 2008-06-19 16:09:02 +0000
@@ -35,6 +35,9 @@
# chmod bits but don't provide an ftp server that support them, well, better
# find another provider ;-)
+# TODO: The message emitted in verbose mode displays local paths. That may be
+# scary for the user when we say 'Deleting <path>' and are referring to
+# remote files...
from bzrlib import (
commands,
@@ -42,11 +45,14 @@
option,
)
lazy_import.lazy_import(globals(), """
+import stat
+
from bzrlib import (
branch,
errors,
revisionspec,
transport,
+ osutils,
urlutils,
workingtree,
)
@@ -84,7 +90,7 @@
wt = workingtree.WorkingTree.open(directory)
changes = wt.changes_from(wt.basis_tree())
-
+
if revision is None and changes.has_changed():
raise errors.UncommittedChanges(wt)
@@ -146,10 +152,46 @@
self.outf.write('Uploading %s\n' % relpath)
self.to_transport.put_bytes(relpath, self.tree.get_file_text(id))
+ def upload_file_robustly(self, relpath, id):
+ """Upload a file, clearing the way on the remote side.
+
+ When doing a full upload, it may happen that a directory exists where
+ we want to put our file.
+ """
+ try:
+ st = self.to_transport.stat(relpath)
+ if stat.S_ISDIR(st.st_mode):
+ # A simple rmdir may not be enough
+ if not self.quiet:
+ self.outf.write('Clearing %s/%s\n' % (
+ self.to_transport.external_url(), relpath))
+ self.to_transport.delete_tree(relpath)
+ except errors.PathError:
+ pass
+ self.upload_file(relpath, id)
+
def make_remote_dir(self, relpath):
# XXX: handle mode
self.to_transport.mkdir(relpath)
+ def make_remote_dir_robustly(self, relpath):
+ """Create a remote directory, clearing the way on the remote side.
+
+ When doing a full upload, it may happen that a file exists where we
+ want to create our directory.
+ """
+ # XXX: handle mode
+ try:
+ st = self.to_transport.stat(relpath)
+ if not stat.S_ISDIR(st.st_mode):
+ if not self.quiet:
+ self.outf.write('Deleting %s/%s\n' % (
+ self.to_transport.external_url(), relpath))
+ self.to_transport.delete(relpath)
+ except errors.PathError:
+ pass
+ self.make_remote_dir(relpath)
+
def delete_remote_file(self, relpath):
if not self.quiet:
self.outf.write('Deleting %s\n' % relpath)
@@ -213,23 +255,16 @@
# --create-prefix option ?)
self.tree.lock_read()
try:
- for dp, ie in self.tree.inventory.iter_entries():
- if dp in ('', '.bzrignore'):
+ for relpath, ie in self.tree.inventory.iter_entries():
+ if relpath in ('', '.bzrignore'):
# skip root ('')
# .bzrignore has no meaning outside of a working tree
# so do not upload it
continue
- # XXX: We need to be more robust in case we upload on top of an
- # existing tree which may contains existing files or dirs whose
- # names will make attempts to upload dirs or files fail.
if ie.kind == 'file':
- self.upload_file(dp, ie.file_id)
+ self.upload_file_robustly(relpath, ie.file_id)
elif ie.kind == 'directory':
- try:
- self.make_remote_dir(dp)
- except errors.FileExists:
- # The directory existed before the upload
- pass
+ self.make_remote_dir_robustly(relpath)
else:
raise NotImplementedError
self.set_uploaded_revid(self.rev_id)
=== modified file 'tests/test_upload.py'
--- a/tests/test_upload.py 2008-05-21 10:22:36 +0000
+++ b/tests/test_upload.py 2008-06-19 16:09:02 +0000
@@ -184,8 +184,11 @@
self.tree.commit('change %s from dir to file' % name)
def transform_file_into_dir(self, name, base=branch_dir):
- osutils.delete_any(base + name)
+ # bzr can't handle that kind change in a single commit without an
+ # intervening bzr status (see bug #205636).
+ self.tree.remove([name], keep_files=False)
os.mkdir(base + name)
+ self.tree.add(name)
self.tree.commit('change %s from file to dir' % name)
def _get_cmd_upload(self):
@@ -217,6 +220,7 @@
self.make_local_branch()
self.do_full_upload()
self.add_file('hello', 'foo')
+
self.do_upload()
self.assertUpFileEqual('foo', 'hello')
@@ -228,7 +232,9 @@
self.add_file('dir/goodbye', 'baz')
self.failIfUpFileExists('dir/goodbye')
+
self.do_upload()
+
self.assertUpFileEqual('baz', 'dir/goodbye')
def test_modify_file(self):
@@ -238,7 +244,9 @@
self.modify_file('hello', 'bar')
self.assertUpFileEqual('foo', 'hello')
+
self.do_upload()
+
self.assertUpFileEqual('bar', 'hello')
def test_rename_one_file(self):
@@ -248,7 +256,9 @@
self.rename_any('hello', 'goodbye')
self.assertUpFileEqual('foo', 'hello')
+
self.do_upload()
+
self.assertUpFileEqual('foo', 'goodbye')
def test_rename_two_files(self):
@@ -263,7 +273,9 @@
self.assertUpFileEqual('foo', 'a')
self.assertUpFileEqual('qux', 'b')
+
self.do_upload()
+
self.assertUpFileEqual('foo', 'b')
self.assertUpFileEqual('qux', 'c')
@@ -274,17 +286,20 @@
self.modify_file('hello', 'bar') # rev3
self.failIfUpFileExists('hello')
+
revspec = revisionspec.RevisionSpec.from_string('2')
self.do_upload(revision=[revspec])
+
self.assertUpFileEqual('foo', 'hello')
- def test_upload_when_changes(self):
+ def test_no_upload_when_changes(self):
self.make_local_branch()
self.add_file('a', 'foo')
self.set_file_content('a', 'bar')
+
self.assertRaises(errors.UncommittedChanges, self.do_upload)
- def test_upload_when_conflicts(self):
+ def test_no_upload_when_conflicts(self):
self.make_local_branch()
self.add_file('a', 'foo')
self.run_bzr('branch branch other')
@@ -292,9 +307,38 @@
other_tree = workingtree.WorkingTree.open('other')
self.set_file_content('a', 'baz', 'other/')
other_tree.commit('modify file a')
+
self.run_bzr('merge -d branch other', retcode=1)
+
self.assertRaises(errors.UncommittedChanges, self.do_upload)
+ def test_change_file_into_dir(self):
+ self.make_local_branch()
+ self.add_file('hello', 'foo')
+ self.do_full_upload()
+ self.transform_file_into_dir('hello')
+ self.add_file('hello/file', 'bar')
+
+ self.assertUpFileEqual('foo', 'hello')
+
+ self.do_upload()
+
+ self.assertUpFileEqual('bar', 'hello/file')
+
+ def test_change_dir_into_file(self):
+ self.make_local_branch()
+ self.add_dir('hello')
+ self.add_file('hello/file', 'foo')
+ self.do_full_upload()
+ self.delete_any('hello/file')
+ self.transform_dir_into_file('hello', 'bar')
+
+ self.assertUpFileEqual('foo', 'hello/file')
+
+ self.do_upload()
+
+ self.assertUpFileEqual('bar', 'hello')
+
class TestFullUpload(tests.TestCaseWithTransport, TestUploadMixin):
@@ -329,7 +373,9 @@
self.delete_any('hello')
self.assertUpFileEqual('foo', 'hello')
+
self.do_upload()
+
self.failIfUpFileExists('hello')
def test_delete_dir_and_subdir(self):
@@ -343,7 +389,9 @@
self.delete_any('dir')
self.assertUpFileEqual('foo', 'dir/subdir/a')
+
self.do_upload()
+
self.failIfUpFileExists('dir/subdir/a')
self.failIfUpFileExists('dir/subdir')
self.failIfUpFileExists('dir')
@@ -358,7 +406,9 @@
self.rename_any('b', 'a')
self.assertUpFileEqual('foo', 'a')
+
self.do_upload()
+
self.failIfUpFileExists('b')
self.assertUpFileEqual('bar', 'a')
@@ -371,43 +421,21 @@
self.delete_any('dir')
self.assertUpFileEqual('foo', 'dir/a')
+
self.do_upload()
+
self.failIfUpFileExists('dir/a')
self.failIfUpFileExists('dir')
self.assertUpFileEqual('foo', 'a')
- # XXX: full upload doesn't handle kind changes
-
- def test_change_file_into_dir(self):
- raise tests.KnownFailure('bug 205636')
- self.make_local_branch()
- self.add_file('hello', 'foo')
- self.do_full_upload()
- self.transform_file_into_dir('hello')
- self.add_file('hello/file', 'bar')
-
- self.assertUpFileEqual('foo', 'hello')
- self.do_upload()
- self.assertUpFileEqual('bar', 'hello/file')
-
- def test_change_dir_into_file(self):
- self.make_local_branch()
- self.add_dir('hello')
- self.add_file('hello/file', 'foo')
- self.do_full_upload()
- self.delete_any('hello/file')
- self.transform_dir_into_file('hello', 'bar')
-
- self.assertUpFileEqual('foo', 'hello/file')
- self.do_upload()
- self.assertUpFileEqual('bar', 'hello')
-
def test_upload_for_the_first_time_do_a_full_upload(self):
self.make_local_branch()
self.add_file('hello', 'bar')
self.failIfUpFileExists(cmd_upload.bzr_upload_revid_file_name)
+
self.do_upload()
+
self.assertUpFileEqual('bar', 'hello')
More information about the bazaar-commits
mailing list