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