[Pkg-bazaar-commits] ./bzr-upload/unstable r48: Build new snapshot.
Jelmer Vernooij
jelmer at samba.org
Fri Apr 10 07:23:59 UTC 2009
------------------------------------------------------------
revno: 48
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: debian
timestamp: Fri 2008-08-08 12:51:37 +0200
message:
Build new snapshot.
added:
auto_upload_hook.py
tests/test_auto_upload_hook.py
modified:
README
__init__.py
debian/changelog
setup.py
tests/__init__.py
tests/test_upload.py
------------------------------------------------------------
revno: 43.1.1
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
tests/test_upload.py
------------------------------------------------------------
revno: 43.1.2
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: upload
timestamp: Fri 2008-06-20 17:26:55 +0200
message:
Adding author, no email as bug reports are handled at http://launchpad.net/bzr-upload.
* setup.py:
(author): Added.
modified:
setup.py
------------------------------------------------------------
revno: 43.1.3
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: upload
timestamp: Sun 2008-06-22 18:09:51 +0200
message:
Handle x mode bit for files and provides default mode bits for
directories.
* tests/test_upload.py:
(TestUploadMixin.assertUpPathModeEqual): New helper.
(TestUploadMixin.chmod_file): New helper.
(TestUploadMixin.test_create_file_in_subdir): Complete test.
(TestUploadMixin.test_make_file_executable): New test.
* __init__.py:
(cmd_upload.run): Cosmetic change.
(cmd_upload.upload_file): Provide mode bits depending on the
inventory executable property.
(cmd_upload.make_remote_dir): Provide defulat mode bits.
(cmd_upload.make_remote_dir_robustly): Oops, add a FIXME for the
regression.
modified:
__init__.py
tests/test_upload.py
------------------------------------------------------------
revno: 43.1.4
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: upload
timestamp: Sun 2008-06-22 18:18:27 +0200
message:
Don't fail a full upload on an already existing dir.
* tests/test_upload.py:
(TestFullUpload.test_create_remote_dir_twice): New test.
* __init__.py:
(cmd_upload.make_remote_dir_robustly): Don't try to create the dir
if it already exists.
modified:
__init__.py
tests/test_upload.py
------------------------------------------------------------
revno: 43.1.5
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: upload
timestamp: Fri 2008-06-27 19:40:38 +0200
message:
Plug tests against proftpd if the local_test_sever plugin is
installed and the server launched.
* tests/test_upload.py:
(TransportAdapter._test_permutations): Add profptd tests if
available.
modified:
tests/test_upload.py
------------------------------------------------------------
revno: 43.1.6
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: upload
timestamp: Sun 2008-06-29 09:27:39 +0200
message:
Fix typo.
* setup.py:
Add missing ','.
modified:
setup.py
------------------------------------------------------------
revno: 43.1.7
committer: Martin Albisetti <argentina at gmail.com>
branch nick: upload
timestamp: Fri 2008-08-01 16:15:06 -0300
message:
Add --auto option to auto-upload on commit (James Westby)
added:
auto_upload_hook.py
tests/test_auto_upload_hook.py
modified:
README
__init__.py
tests/__init__.py
tests/test_upload.py
------------------------------------------------------------
revno: 43.2.1
committer: James Westby <jw+debian at jameswestby.net>
branch nick: upload
timestamp: Fri 2008-08-01 15:22:10 +0100
message:
Switch most of the logic to a class outside of the command class.
This makes it easier to re-use that logic from other code.
modified:
__init__.py
tests/test_upload.py
------------------------------------------------------------
revno: 43.2.2
committer: James Westby <jw+debian at jameswestby.net>
branch nick: upload
timestamp: Fri 2008-08-01 16:02:31 +0100
message:
Add a post_change_branch_tip hook to upload.
If auto_upload is set to "True" for a branch, then any changes
to the branch will trigger and upload run to the upload location
for that branch.
added:
auto_upload_hook.py
modified:
__init__.py
------------------------------------------------------------
revno: 43.2.3
committer: James Westby <jw+debian at jameswestby.net>
branch nick: upload
timestamp: Fri 2008-08-01 19:58:57 +0100
message:
Add some tests for the hook, rename the option to "upload_auto"
added:
tests/test_auto_upload_hook.py
modified:
__init__.py
auto_upload_hook.py
tests/__init__.py
------------------------------------------------------------
revno: 43.2.4
committer: James Westby <jw+debian at jameswestby.net>
branch nick: upload
timestamp: Fri 2008-08-01 19:59:48 +0100
message:
Add the groundwork for --auto that enables the hook for a branch.
modified:
__init__.py
tests/test_upload.py
------------------------------------------------------------
revno: 43.2.5
committer: James Westby <jw+debian at jameswestby.net>
branch nick: upload
timestamp: Fri 2008-08-01 19:59:59 +0100
message:
Hook up the --upload option and document it.
modified:
README
__init__.py
------------------------------------------------------------
revno: 43.1.8
committer: Martin Albisetti <argentina at gmail.com>
branch nick: upload
timestamp: Sat 2008-08-02 16:14:26 -0300
message:
Fix the way the working tree is accessed so you can upload in subdirs. bug #248529 (James Westby)
modified:
__init__.py
tests/test_upload.py
------------------------------------------------------------
revno: 43.3.1
committer: James Westby <jw+debian at jameswestby.net>
branch nick: upload
timestamp: Sat 2008-08-02 16:54:28 +0100
message:
Use open_containing rather than open, so that you can upload from a subdir.
modified:
__init__.py
tests/test_upload.py
-------------- next part --------------
=== modified file 'README'
--- a/README 2008-05-20 01:38:17 +0000
+++ b/README 2008-08-01 18:59:59 +0000
@@ -43,6 +43,27 @@
bzr upload --full sftp://user@host/location/on/webserver
+Automatically Uploading
+-----------------------
+
+bzr-upload comes with a hook that can be used to trigger an upload whenever
+the tip of the branch changes, including on commit, push, uncommit etc. This
+would allow you to keep the code on the target up to date automatically.
+
+The easiest way to enable this is to run upload with the --auto option.
+
+ bzr upload --auto
+
+will enable the hook for this branch. If you were to do a commit in this branch
+now you would see it trigger the upload automatically.
+
+If you wish to disable this for a branch again then you can use the --no-auto
+option.
+
+ bzr upload --no-auto
+
+will disable the feature for that branch.
+
Collaborating
-------------
=== modified file '__init__.py'
--- a/__init__.py 2008-06-12 16:39:04 +0000
+++ b/__init__.py 2008-08-08 10:51:37 +0000
@@ -35,18 +35,24 @@
# 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 (
+ branch,
commands,
lazy_import,
option,
)
lazy_import.lazy_import(globals(), """
+import stat
+
from bzrlib import (
- branch,
errors,
revisionspec,
transport,
+ osutils,
urlutils,
workingtree,
)
@@ -55,82 +61,46 @@
version_info = (0,1,0)
plugin_name = 'upload'
-class cmd_upload(commands.Command):
- """Upload a working tree, as a whole or incrementally.
-
- If no destination is specified use the last one used.
- If no revision is specified upload the changes since the last upload.
- """
- takes_args = ['location?']
- takes_options = [
- 'revision',
- 'remember',
- option.Option('full', 'Upload the full working tree.'),
- option.Option('quiet', 'Do not output what is being done.',
- short_name='q'),
- option.Option('directory',
- help='Branch to upload from, '
- 'rather than the one containing the working directory.',
- short_name='d',
- type=unicode,
- ),
- ]
-
- def run(self, location=None, full=False, revision=None, remember=None,
- directory=None, quiet=False,
- ):
- if directory is None:
- directory = u'.'
-
- wt = workingtree.WorkingTree.open(directory)
- changes = wt.changes_from(wt.basis_tree())
-
- if revision is None and changes.has_changed():
- raise errors.UncommittedChanges(wt)
-
- self.branch = wt.branch
-
- if location is None:
- stored_loc = self.get_upload_location()
- if stored_loc is None:
- raise errors.BzrCommandError('No upload location'
- ' known or specified.')
- else:
- # FIXME: Not currently tested
- display_url = urlutils.unescape_for_display(stored_loc,
- self.outf.encoding)
- self.outf.write("Using saved location: %s\n" % display_url)
- location = stored_loc
-
- self.to_transport = transport.get_transport(location)
- if revision is None:
- rev_id = self.branch.last_revision()
- else:
- if len(revision) != 1:
- raise errors.BzrCommandError(
- 'bzr upload --revision takes exactly 1 argument')
- rev_id = revision[0].in_history(self.branch).rev_id
-
- self.tree = self.branch.repository.revision_tree(rev_id)
+
+def _get_branch_option(branch, option):
+ return branch.get_config().get_user_option(option)
+
+def _set_branch_option(branch, option, value):
+ branch.get_config().set_user_option(option, value)
+
+def get_upload_location(branch):
+ return _get_branch_option(branch, 'upload_location')
+
+def set_upload_location(branch, location):
+ _set_branch_option(branch, 'upload_location', location)
+
+def get_upload_auto(branch):
+ result = _get_branch_option(branch, 'upload_auto')
+ # FIXME: is there a better way to do this with bzr's config API?
+ if result is not None and result.strip() == "True":
+ return True
+ return False
+
+def set_upload_auto(branch, auto):
+ if auto:
+ auto_str = "True"
+ else:
+ auto_str = "False"
+ _set_branch_option(branch, 'upload_auto', auto_str)
+
+
+class BzrUploader(object):
+
+ def __init__(self, branch, to_transport, outf, tree, rev_id,
+ quiet=False):
+ self.branch = branch
+ self.to_transport = to_transport
+ self.outf = outf
+ self.tree = tree
self.rev_id = rev_id
- self._pending_renames = []
+ self.quiet = quiet
self._pending_deletions = []
- self.quiet = quiet
-
- if full:
- self.upload_full_tree()
- else:
- self.upload_tree()
-
- # We uploaded successfully, remember it
- if self.get_upload_location() is None or remember:
- self.set_upload_location(self.to_transport.base)
-
- def set_upload_location(self, location):
- self.branch.get_config().set_user_option('upload_location', location)
-
- def get_upload_location(self):
- return self.branch.get_config().get_user_option('upload_location')
+ self._pending_renames = []
bzr_upload_revid_file_name = '.bzr-upload.revid'
@@ -141,14 +111,58 @@
def get_uploaded_revid(self):
return self.to_transport.get_bytes(self.bzr_upload_revid_file_name)
- def upload_file(self, relpath, id):
+ def upload_file(self, relpath, id, mode=None):
+ if mode is None:
+ if self.tree.is_executable(id):
+ mode = 0775
+ else:
+ mode = 0664
if not self.quiet:
self.outf.write('Uploading %s\n' % relpath)
- self.to_transport.put_bytes(relpath, self.tree.get_file_text(id))
-
- def make_remote_dir(self, relpath):
- # XXX: handle mode
- self.to_transport.mkdir(relpath)
+ self.to_transport.put_bytes(relpath, self.tree.get_file_text(id), mode)
+
+ def upload_file_robustly(self, relpath, id, mode=None):
+ """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, mode)
+
+ def make_remote_dir(self, relpath, mode=None):
+ if mode is None:
+ mode = 0775
+ self.to_transport.mkdir(relpath, mode)
+
+ def make_remote_dir_robustly(self, relpath, mode=None):
+ """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.
+ """
+ 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)
+ else:
+ # Ok the remote dir already exists, nothing to do
+ return
+ except errors.PathError:
+ pass
+ self.make_remote_dir(relpath, mode)
def delete_remote_file(self, relpath):
if not self.quiet:
@@ -213,23 +227,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("don't known how to upload %r" % ie.kind)
self.set_uploaded_revid(self.rev_id)
@@ -312,9 +319,92 @@
self.tree.unlock()
+class cmd_upload(commands.Command):
+ """Upload a working tree, as a whole or incrementally.
+
+ If no destination is specified use the last one used.
+ If no revision is specified upload the changes since the last upload.
+ """
+ takes_args = ['location?']
+ takes_options = [
+ 'revision',
+ 'remember',
+ option.Option('full', 'Upload the full working tree.'),
+ option.Option('quiet', 'Do not output what is being done.',
+ short_name='q'),
+ option.Option('directory',
+ help='Branch to upload from, '
+ 'rather than the one containing the working directory.',
+ short_name='d',
+ type=unicode,
+ ),
+ option.Option('auto',
+ 'Trigger an upload from this branch whenever the tip '
+ 'revision changes.')
+ ]
+
+ def run(self, location=None, full=False, revision=None, remember=None,
+ directory=None, quiet=False, auto=None
+ ):
+ if directory is None:
+ directory = u'.'
+
+ wt = workingtree.WorkingTree.open_containing(directory)[0]
+ changes = wt.changes_from(wt.basis_tree())
+
+ if revision is None and changes.has_changed():
+ raise errors.UncommittedChanges(wt)
+
+ branch = wt.branch
+
+ if location is None:
+ stored_loc = get_upload_location(branch)
+ if stored_loc is None:
+ raise errors.BzrCommandError('No upload location'
+ ' known or specified.')
+ else:
+ # FIXME: Not currently tested
+ display_url = urlutils.unescape_for_display(stored_loc,
+ self.outf.encoding)
+ self.outf.write("Using saved location: %s\n" % display_url)
+ location = stored_loc
+
+ to_transport = transport.get_transport(location)
+ if revision is None:
+ rev_id = branch.last_revision()
+ else:
+ if len(revision) != 1:
+ raise errors.BzrCommandError(
+ 'bzr upload --revision takes exactly 1 argument')
+ rev_id = revision[0].in_history(branch).rev_id
+
+ tree = branch.repository.revision_tree(rev_id)
+
+ uploader = BzrUploader(branch, to_transport, self.outf, tree,
+ rev_id, quiet=quiet)
+
+ if full:
+ uploader.upload_full_tree()
+ else:
+ uploader.upload_tree()
+
+ # We uploaded successfully, remember it
+ if get_upload_location(branch) is None or remember:
+ set_upload_location(branch, to_transport.base)
+ if auto is not None:
+ set_upload_auto(branch, auto)
+
+
commands.register_command(cmd_upload)
+from bzrlib.plugins.upload.auto_upload_hook import auto_upload_hook
+
+branch.Branch.hooks.install_named_hook('post_change_branch_tip',
+ auto_upload_hook,
+ 'Auto upload code from a branch when it is changed.')
+
+
def load_tests(basic_tests, module, loader):
# This module shouldn't define any tests but I don't know how to report
# that. I prefer to update basic_tests with the other tests to detect
=== added file 'auto_upload_hook.py'
--- a/auto_upload_hook.py 1970-01-01 00:00:00 +0000
+++ b/auto_upload_hook.py 2008-08-01 18:58:57 +0000
@@ -0,0 +1,47 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import sys
+
+
+from bzrlib import branch, transport, urlutils
+
+
+from bzrlib.plugins.upload import (
+ BzrUploader,
+ get_upload_location,
+ get_upload_auto,
+ )
+
+
+def auto_upload_hook(params, quiet=False):
+ source_branch = params.branch
+ destination = get_upload_location(source_branch)
+ if destination is None:
+ return
+ auto_upload = get_upload_auto(source_branch)
+ if not auto_upload:
+ return
+ if not quiet:
+ display_url = urlutils.unescape_for_display(destination,
+ sys.stdout.encoding)
+ print "Automatically uploading to %s" % display_url
+ to_transport = transport.get_transport(destination)
+ last_revision = source_branch.last_revision()
+ last_tree = source_branch.repository.revision_tree(last_revision)
+ uploader = BzrUploader(source_branch, to_transport, sys.stdout,
+ last_tree, last_revision, quiet=quiet)
+ uploader.upload_tree()
=== modified file 'debian/changelog'
--- a/debian/changelog 2008-06-19 17:21:26 +0000
+++ b/debian/changelog 2008-08-08 10:51:37 +0000
@@ -1,3 +1,9 @@
+bzr-upload (0.1.0~bzr51-1) unstable; urgency=low
+
+ * New upstream snapshot.
+
+ -- Jelmer Vernooij <jelmer at samba.org> Fri, 08 Aug 2008 12:50:35 +0200
+
bzr-upload (0.1.0~bzr44-1) unstable; urgency=low
* Initial release. (Closes: #487106)
=== modified file 'setup.py'
--- a/setup.py 2008-05-22 20:56:07 +0000
+++ b/setup.py 2008-06-29 07:27:39 +0000
@@ -23,6 +23,7 @@
version='0.1.0',
url='http://launchpad.net/bzr-upload',
download_url='http://launchpad.net/bzr-upload',
+ author='Vincent Ladeuil, Martin Albisetti',
license='GPL',
long_description="""
Web sites are often hosted on servers where bzr can't be installed. In
=== modified file 'tests/__init__.py'
--- a/tests/__init__.py 2008-05-21 10:22:36 +0000
+++ b/tests/__init__.py 2008-08-01 18:58:57 +0000
@@ -20,6 +20,7 @@
# unwanted tests and I think that's sufficient.
testmod_names = [
+ 'test_auto_upload_hook',
'test_upload',
]
basic_tests.addTest(loader.loadTestsFromModuleNames(
=== added file 'tests/test_auto_upload_hook.py'
--- a/tests/test_auto_upload_hook.py 1970-01-01 00:00:00 +0000
+++ b/tests/test_auto_upload_hook.py 2008-08-01 18:58:57 +0000
@@ -0,0 +1,89 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+
+from bzrlib.branch import Branch
+from bzrlib.tests import TestCaseWithTransport
+
+from bzrlib.plugins.upload import set_upload_location, set_upload_auto
+from bzrlib.plugins.upload.auto_upload_hook import auto_upload_hook
+
+# Hooks are disabled during tests, so that they don't cause havoc
+# with a users system. What we will test is that the hook was
+# correctly registered, and then set up the scenarios and trigger
+# it manually
+
+class AutoPushHookTests(TestCaseWithTransport):
+
+ def make_start_branch(self, location=True, auto=True):
+ self.wt = self.make_branch_and_tree('.')
+ self.build_tree(['a'])
+ self.wt.add(['a'])
+ self.wt.commit("one")
+ if location:
+ set_upload_location(self.wt.branch, self.target_location())
+ if auto:
+ set_upload_auto(self.wt.branch, True)
+
+ def target_location(self):
+ return self.get_url('target')
+
+ def get_params(self):
+ class FakeParams(object):
+ def __init__(self, branch):
+ self.branch = branch
+ return FakeParams(self.wt.branch)
+
+ def test_hook_is_registered(self):
+ # Hooks are stored in self._preserved_hooks
+ self.assertTrue(auto_upload_hook in
+ self._preserved_hooks[Branch]['post_change_branch_tip'])
+
+ def test_auto_push_on_commit(self):
+ self.make_start_branch()
+ self.failIfExists('target')
+ self.build_tree(['b'])
+ self.wt.add(['b'])
+ self.wt.commit("two")
+ auto_upload_hook(self.get_params(), quiet=True)
+ self.failUnlessExists('target')
+ self.failUnlessExists(os.path.join('target', 'a'))
+ self.failUnlessExists(os.path.join('target', 'b'))
+
+ def test_disable_auto_push(self):
+ self.make_start_branch()
+ self.failIfExists('target')
+ self.build_tree(['b'])
+ self.wt.add(['b'])
+ self.wt.commit("two")
+ auto_upload_hook(self.get_params(), quiet=True)
+ set_upload_auto(self.wt.branch, False)
+ self.build_tree(['c'])
+ self.wt.add(['c'])
+ self.wt.commit("three")
+ auto_upload_hook(self.get_params(), quiet=True)
+ self.failIfExists(os.path.join('target', 'c'))
+
+ def test_dont_push_if_no_location(self):
+ self.make_start_branch(location=False)
+ self.failIfExists('target')
+ self.build_tree(['b'])
+ self.wt.add(['b'])
+ self.wt.commit("two")
+ auto_upload_hook(self.get_params(), quiet=True)
+ self.failIfExists('target')
+
=== modified file 'tests/test_upload.py'
--- a/tests/test_upload.py 2008-05-21 10:22:36 +0000
+++ b/tests/test_upload.py 2008-08-02 15:54:28 +0000
@@ -15,6 +15,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import os
+import stat
import sys
@@ -37,7 +38,7 @@
)
-from bzrlib.plugins.upload import cmd_upload
+from bzrlib.plugins.upload import cmd_upload, BzrUploader, get_upload_auto
class TransportAdapter(
@@ -66,6 +67,25 @@
# Continue even if a dependency prevents us
# from adding this test
pass
+ try:
+ import bzrlib.plugins.local_test_server
+ from bzrlib.plugins.local_test_server import test_server
+ if False:
+ # XXX: Disable since we can't get chmod working for anonymous
+ # user
+ scenario = ('vsftpd',
+ {'transport_class': test_server.FtpTransport,
+ 'transport_server': test_server.Vsftpd,
+ })
+ result.append(scenario)
+ if test_server.ProftpdFeature().available():
+ scenario = ('proftpd',
+ {'transport_class': test_server.FtpTransport,
+ 'transport_server': test_server.Proftpd,
+ })
+ result.append(scenario)
+ except ImportError:
+ pass
return result
@@ -143,6 +163,20 @@
def assertUpFileEqual(self, content, path, base=upload_dir):
self.assertFileEqual(content, base + path)
+ def assertUpPathModeEqual(self, path, expected_mode, base=upload_dir):
+ # FIXME: the tests needing that assertion should depend on the server
+ # ability to handle chmod so that they don't fail (or be skipped)
+ # against servers that can't. Note that some bzrlib transports define
+ # _can_roundtrip_unix_modebits in a incomplete way, this property
+ # should depend on both the client and the server, not the client only.
+ st = os.stat(base + path)
+ mode = st.st_mode & 0777
+ if expected_mode == mode:
+ return
+ raise AssertionError(
+ 'For path %s, mode is %s not %s' %
+ (base + path, oct(mode), oct(expected_mode)))
+
def failIfUpFileExists(self, path, base=upload_dir):
self.failIfExists(base + path)
@@ -165,6 +199,11 @@
self.set_file_content(name, content, base)
self.tree.commit('modify file %s' % name)
+ def chmod_file(self, name, mode, base=branch_dir):
+ path = base + name
+ os.chmod(path, mode)
+ self.tree.commit('change file %s mode to %s' % (name, oct(mode)))
+
def delete_any(self, name, base=branch_dir):
self.tree.remove([name], keep_files=False)
self.tree.commit('delete %s' % name)
@@ -184,8 +223,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 +259,7 @@
self.make_local_branch()
self.do_full_upload()
self.add_file('hello', 'foo')
+
self.do_upload()
self.assertUpFileEqual('foo', 'hello')
@@ -228,8 +271,11 @@
self.add_file('dir/goodbye', 'baz')
self.failIfUpFileExists('dir/goodbye')
+
self.do_upload()
+
self.assertUpFileEqual('baz', 'dir/goodbye')
+ self.assertUpPathModeEqual('dir', 0775)
def test_modify_file(self):
self.make_local_branch()
@@ -238,7 +284,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 +296,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 +313,9 @@
self.assertUpFileEqual('foo', 'a')
self.assertUpFileEqual('qux', 'b')
+
self.do_upload()
+
self.assertUpFileEqual('foo', 'b')
self.assertUpFileEqual('qux', 'c')
@@ -274,17 +326,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 +347,90 @@
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')
+
+ def test_make_file_executable(self):
+ self.make_local_branch()
+ self.add_file('hello', 'foo')
+ self.chmod_file('hello', 0664)
+ self.do_full_upload()
+ self.chmod_file('hello', 0755)
+
+ self.assertUpPathModeEqual('hello', 0664)
+
+ self.do_upload()
+
+ self.assertUpPathModeEqual('hello', 0775)
+
+ def test_upload_auto(self):
+ """Test that upload --auto sets the upload_auto option"""
+ self.make_local_branch()
+ self.add_file('hello', 'foo')
+ self.assertFalse(get_upload_auto(self.tree.branch))
+ self.do_full_upload(auto=True)
+ self.assertUpFileEqual('foo', 'hello')
+ self.assertTrue(get_upload_auto(self.tree.branch))
+ # and check that it stays set until it is unset
+ self.add_file('bye', 'bar')
+ self.do_full_upload()
+ self.assertUpFileEqual('bar', 'bye')
+ self.assertTrue(get_upload_auto(self.tree.branch))
+
+ def test_upload_noauto(self):
+ """Test that upload --no-auto unsets the upload_auto option"""
+ self.make_local_branch()
+ self.add_file('hello', 'foo')
+ self.assertFalse(get_upload_auto(self.tree.branch))
+ self.do_full_upload(auto=True)
+ self.assertUpFileEqual('foo', 'hello')
+ self.assertTrue(get_upload_auto(self.tree.branch))
+ self.add_file('bye', 'bar')
+ self.do_full_upload(auto=False)
+ self.assertUpFileEqual('bar', 'bye')
+ self.assertFalse(get_upload_auto(self.tree.branch))
+ # and check that it stays unset until it is set
+ self.add_file('again', 'baz')
+ self.do_full_upload()
+ self.assertUpFileEqual('baz', 'again')
+ self.assertFalse(get_upload_auto(self.tree.branch))
+
+ def test_upload_from_subdir(self):
+ self.make_local_branch()
+ self.build_tree(['branch/foo/', 'branch/foo/bar'])
+ self.tree.add(['foo/', 'foo/bar'])
+ self.tree.commit("Add directory")
+ self.do_full_upload(directory='branch/foo')
+
class TestFullUpload(tests.TestCaseWithTransport, TestUploadMixin):
@@ -305,7 +441,7 @@
self.do_full_upload()
- self.failUnlessUpFileExists(cmd_upload.bzr_upload_revid_file_name)
+ self.failUnlessUpFileExists(BzrUploader.bzr_upload_revid_file_name)
def test_invalid_revspec(self):
self.make_local_branch()
@@ -315,6 +451,19 @@
self.assertRaises(errors.BzrCommandError,
self.do_incremental_upload, revision=[rev1, rev2])
+ def test_create_remote_dir_twice(self):
+ self.make_local_branch()
+ self.add_dir('dir')
+ self.do_full_upload()
+ self.add_file('dir/goodbye', 'baz')
+
+ self.failIfUpFileExists('dir/goodbye')
+
+ self.do_full_upload()
+
+ self.assertUpFileEqual('baz', 'dir/goodbye')
+ self.assertUpPathModeEqual('dir', 0775)
+
class TestIncrementalUpload(tests.TestCaseWithTransport, TestUploadMixin):
@@ -329,7 +478,9 @@
self.delete_any('hello')
self.assertUpFileEqual('foo', 'hello')
+
self.do_upload()
+
self.failIfUpFileExists('hello')
def test_delete_dir_and_subdir(self):
@@ -343,7 +494,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 +511,9 @@
self.rename_any('b', 'a')
self.assertUpFileEqual('foo', 'a')
+
self.do_upload()
+
self.failIfUpFileExists('b')
self.assertUpFileEqual('bar', 'a')
@@ -371,43 +526,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.failIfUpFileExists(BzrUploader.bzr_upload_revid_file_name)
+
self.do_upload()
+
self.assertUpFileEqual('bar', 'hello')
More information about the Pkg-bazaar-commits
mailing list