# HG changeset patch # User Augie Fackler # Date 1373983795 14400 # Node ID e775ffbcb3590fb969b92903651de01d7bc6eea9 # Parent 2c64453f98a73b7b679de5f7bf0100a7c5bf60d4 push: also suggest user rebase if we get SVN_ERR_FS_ALREADY_EXISTS Subversion differentiates adding an already-added file from transaction being out of date and edit conflicts. Fixes #400. diff --git a/hgsubversion/pushmod.py b/hgsubversion/pushmod.py --- a/hgsubversion/pushmod.py +++ b/hgsubversion/pushmod.py @@ -201,7 +201,8 @@ def commit(ui, repo, rev_ctx, meta, base props, newcopies) except svnwrap.SubversionException, e: if len(e.args) > 0 and e.args[1] in (svnwrap.ERR_FS_TXN_OUT_OF_DATE, - svnwrap.ERR_FS_CONFLICT): + svnwrap.ERR_FS_CONFLICT, + svnwrap.ERR_FS_ALREADY_EXISTS): raise hgutil.Abort('Outgoing changesets parent is not at ' 'subversion HEAD\n' '(pull again and rebase on a newer revision)') diff --git a/hgsubversion/svnwrap/subvertpy_wrapper.py b/hgsubversion/svnwrap/subvertpy_wrapper.py --- a/hgsubversion/svnwrap/subvertpy_wrapper.py +++ b/hgsubversion/svnwrap/subvertpy_wrapper.py @@ -52,6 +52,7 @@ def version(): return (svnvers, 'Subvertpy ' + _versionstr(subvertpy.__version__)) # exported values +ERR_FS_ALREADY_EXISTS = subvertpy.ERR_FS_ALREADY_EXISTS ERR_FS_CONFLICT = subvertpy.ERR_FS_CONFLICT ERR_FS_NOT_FOUND = subvertpy.ERR_FS_NOT_FOUND ERR_FS_TXN_OUT_OF_DATE = subvertpy.ERR_FS_TXN_OUT_OF_DATE @@ -59,11 +60,11 @@ ERR_INCOMPLETE_DATA = subvertpy.ERR_INCO ERR_RA_DAV_PATH_NOT_FOUND = subvertpy.ERR_RA_DAV_PATH_NOT_FOUND ERR_RA_DAV_REQUEST_FAILED = subvertpy.ERR_RA_DAV_REQUEST_FAILED ERR_REPOS_HOOK_FAILURE = subvertpy.ERR_REPOS_HOOK_FAILURE -SSL_UNKNOWNCA = subvertpy.SSL_UNKNOWNCA SSL_CNMISMATCH = subvertpy.SSL_CNMISMATCH -SSL_NOTYETVALID = subvertpy.SSL_NOTYETVALID SSL_EXPIRED = subvertpy.SSL_EXPIRED +SSL_NOTYETVALID = subvertpy.SSL_NOTYETVALID SSL_OTHER = subvertpy.SSL_OTHER +SSL_UNKNOWNCA = subvertpy.SSL_UNKNOWNCA SubversionException = subvertpy.SubversionException apply_txdelta = delta.apply_txdelta_handler # superclass for editor.HgEditor diff --git a/hgsubversion/svnwrap/svn_swig_wrapper.py b/hgsubversion/svnwrap/svn_swig_wrapper.py --- a/hgsubversion/svnwrap/svn_swig_wrapper.py +++ b/hgsubversion/svnwrap/svn_swig_wrapper.py @@ -37,17 +37,18 @@ def version(): return '%d.%d.%d' % current_bindings, 'SWIG' # exported values +ERR_FS_ALREADY_EXISTS = core.SVN_ERR_FS_ALREADY_EXISTS ERR_FS_CONFLICT = core.SVN_ERR_FS_CONFLICT ERR_FS_NOT_FOUND = core.SVN_ERR_FS_NOT_FOUND ERR_FS_TXN_OUT_OF_DATE = core.SVN_ERR_FS_TXN_OUT_OF_DATE ERR_INCOMPLETE_DATA = core.SVN_ERR_INCOMPLETE_DATA ERR_RA_DAV_REQUEST_FAILED = core.SVN_ERR_RA_DAV_REQUEST_FAILED ERR_REPOS_HOOK_FAILURE = core.SVN_ERR_REPOS_HOOK_FAILURE -SSL_UNKNOWNCA = core.SVN_AUTH_SSL_UNKNOWNCA SSL_CNMISMATCH = core.SVN_AUTH_SSL_CNMISMATCH -SSL_NOTYETVALID = core.SVN_AUTH_SSL_NOTYETVALID SSL_EXPIRED = core.SVN_AUTH_SSL_EXPIRED +SSL_NOTYETVALID = core.SVN_AUTH_SSL_NOTYETVALID SSL_OTHER = core.SVN_AUTH_SSL_OTHER +SSL_UNKNOWNCA = core.SVN_AUTH_SSL_UNKNOWNCA SubversionException = core.SubversionException Editor = delta.Editor diff --git a/tests/test_push_command.py b/tests/test_push_command.py --- a/tests/test_push_command.py +++ b/tests/test_push_command.py @@ -50,6 +50,54 @@ class PushTests(test_util.TestBase): tip = self.repo['tip'] self.assertEqual(tip.node(), old_tip) + def test_push_add_of_added_upstream_gives_sane_error(self): + repo = self.repo + def file_callback(repo, memctx, path): + if path == 'adding_file': + return context.memfilectx(path=path, + data='foo', + islink=False, + isexec=False, + copied=False) + raise IOError() + p1 = repo['default'].node() + ctx = context.memctx(repo, + (p1, node.nullid), + 'automated test', + ['adding_file'], + file_callback, + 'an_author', + '2008-10-07 20:59:48 -0500', + {'branch': 'default', }) + new_hash = repo.commitctx(ctx) + hg.update(repo, repo['tip'].node()) + old_tip = repo['tip'].node() + self.pushrevisions() + tip = self.repo['tip'] + self.assertNotEqual(tip.node(), old_tip) + + # This node adds the same file as the first one we added, and + # will be refused by the server for adding a file that already + # exists. We should respond with an error suggesting the user + # rebase. + ctx = context.memctx(repo, + (p1, node.nullid), + 'automated test', + ['adding_file'], + file_callback, + 'an_author', + '2008-10-07 20:59:48 -0500', + {'branch': 'default', }) + new_hash = repo.commitctx(ctx) + hg.update(repo, repo['tip'].node()) + old_tip = repo['tip'].node() + try: + self.pushrevisions() + except hgutil.Abort, e: + assert "pull again and rebase" in str(e) + tip = self.repo['tip'] + self.assertEqual(tip.node(), old_tip) + def test_cant_push_with_changes(self): repo = self.repo def file_callback(repo, memctx, path):