2010-07-14 17:39:18 +04:00
|
|
|
import test_util
|
|
|
|
|
2009-05-15 21:18:43 +04:00
|
|
|
import atexit
|
2010-01-26 19:36:13 +03:00
|
|
|
import errno
|
2008-10-08 07:13:14 +04:00
|
|
|
import os
|
2012-04-12 17:39:17 +04:00
|
|
|
import sys
|
2009-05-15 21:18:43 +04:00
|
|
|
import random
|
2009-05-28 06:40:58 +04:00
|
|
|
import shutil
|
2008-10-30 05:15:36 +03:00
|
|
|
import socket
|
2008-11-10 03:08:35 +03:00
|
|
|
import subprocess
|
2008-10-08 07:13:14 +04:00
|
|
|
import unittest
|
|
|
|
|
|
|
|
from mercurial import context
|
2009-05-15 21:18:43 +04:00
|
|
|
from mercurial import commands
|
2008-10-08 07:13:14 +04:00
|
|
|
from mercurial import hg
|
|
|
|
from mercurial import node
|
|
|
|
from mercurial import revlog
|
2009-04-25 05:31:17 +04:00
|
|
|
from mercurial import util as hgutil
|
2008-10-08 07:13:14 +04:00
|
|
|
|
2008-10-30 05:15:36 +03:00
|
|
|
import time
|
|
|
|
|
2008-10-08 07:13:14 +04:00
|
|
|
|
2008-11-15 01:18:24 +03:00
|
|
|
class PushTests(test_util.TestBase):
|
2008-11-01 20:23:07 +03:00
|
|
|
def setUp(self):
|
2008-11-15 01:18:24 +03:00
|
|
|
test_util.TestBase.setUp(self)
|
2012-04-19 20:29:32 +04:00
|
|
|
self.repo_path = self.load_and_fetch('simple_branch.svndump')[1]
|
2008-10-08 07:13:14 +04:00
|
|
|
|
2009-03-29 01:50:00 +03:00
|
|
|
def test_cant_push_empty_ctx(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()
|
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'automated test',
|
|
|
|
[],
|
|
|
|
file_callback,
|
|
|
|
'an_author',
|
|
|
|
'2008-10-07 20:59:48 -0500',
|
2011-10-12 11:35:25 +04:00
|
|
|
{'branch': 'default', })
|
2009-03-29 01:50:00 +03:00
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
|
|
|
old_tip = repo['tip'].node()
|
|
|
|
self.pushrevisions()
|
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertEqual(tip.node(), old_tip)
|
|
|
|
|
2009-07-19 05:44:33 +04:00
|
|
|
def test_cant_push_with_changes(self):
|
|
|
|
repo = self.repo
|
|
|
|
def file_callback(repo, memctx, path):
|
|
|
|
return context.memfilectx(
|
2010-02-14 23:04:56 +03:00
|
|
|
path=path, data='foo', islink=False,
|
2009-07-19 05:44:33 +04:00
|
|
|
isexec=False, copied=False)
|
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'automated test',
|
|
|
|
['adding_file'],
|
|
|
|
file_callback,
|
|
|
|
'an_author',
|
|
|
|
'2008-10-07 20:59:48 -0500',
|
2011-10-12 11:35:25 +04:00
|
|
|
{'branch': 'default', })
|
2009-07-19 05:44:33 +04:00
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
|
|
|
# Touch an existing file
|
|
|
|
repo.wwrite('beta', 'something else', '')
|
|
|
|
try:
|
|
|
|
self.pushrevisions()
|
|
|
|
except hgutil.Abort:
|
|
|
|
pass
|
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertEqual(new_hash, tip.node())
|
|
|
|
|
2010-07-28 16:47:44 +04:00
|
|
|
def internal_push_over_svnserve(self, subdir='', commit=True):
|
2012-04-19 20:29:28 +04:00
|
|
|
repo_path = self.load_svndump('simple_branch.svndump')
|
|
|
|
open(os.path.join(repo_path, 'conf', 'svnserve.conf'),
|
2009-05-13 19:22:18 +04:00
|
|
|
'w').write('[general]\nanon-access=write\n[sasl]\n')
|
|
|
|
self.port = random.randint(socket.IPPORT_USERRESERVED, 65535)
|
|
|
|
self.host = 'localhost'
|
|
|
|
args = ['svnserve', '--daemon', '--foreground',
|
|
|
|
'--listen-port=%d' % self.port,
|
|
|
|
'--listen-host=%s' % self.host,
|
2012-04-19 20:29:28 +04:00
|
|
|
'--root=%s' % repo_path]
|
2009-05-13 19:22:18 +04:00
|
|
|
|
2009-05-19 13:43:49 +04:00
|
|
|
svnserve = subprocess.Popen(args, stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.STDOUT)
|
|
|
|
self.svnserve_pid = svnserve.pid
|
2009-05-13 19:22:18 +04:00
|
|
|
try:
|
|
|
|
time.sleep(2)
|
2009-05-14 06:39:39 +04:00
|
|
|
import shutil
|
|
|
|
shutil.rmtree(self.wc_path)
|
2010-07-28 16:47:44 +04:00
|
|
|
commands.clone(self.ui(),
|
|
|
|
'svn://%s:%d/%s' % (self.host, self.port, subdir),
|
2009-05-13 19:22:18 +04:00
|
|
|
self.wc_path, noupdate=True)
|
|
|
|
|
|
|
|
repo = self.repo
|
|
|
|
old_tip = repo['tip'].node()
|
|
|
|
expected_parent = repo['default'].node()
|
|
|
|
def file_callback(repo, memctx, path):
|
|
|
|
if path == 'adding_file':
|
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='foo',
|
|
|
|
islink=False,
|
|
|
|
isexec=False,
|
|
|
|
copied=False)
|
2010-01-26 19:36:13 +03:00
|
|
|
raise IOError(errno.EINVAL, 'Invalid operation: ' + path)
|
2009-05-13 19:22:18 +04:00
|
|
|
ctx = context.memctx(repo,
|
2009-05-22 15:41:21 +04:00
|
|
|
parents=(repo['default'].node(), node.nullid),
|
|
|
|
text='automated test',
|
|
|
|
files=['adding_file'],
|
|
|
|
filectxfn=file_callback,
|
|
|
|
user='an_author',
|
|
|
|
date='2008-10-07 20:59:48 -0500',
|
2011-10-12 11:35:25 +04:00
|
|
|
extra={'branch': 'default', })
|
2009-05-13 19:22:18 +04:00
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
if not commit:
|
|
|
|
return # some tests use this test as an extended setup.
|
|
|
|
hg.update(repo, repo['tip'].node())
|
|
|
|
oldauthor = repo['tip'].user()
|
|
|
|
commands.push(repo.ui, repo)
|
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(oldauthor, tip.user())
|
|
|
|
self.assertNotEqual(tip.node(), old_tip)
|
|
|
|
self.assertEqual(tip.parents()[0].node(), expected_parent)
|
|
|
|
self.assertEqual(tip['adding_file'].data(), 'foo')
|
|
|
|
self.assertEqual(tip.branch(), 'default')
|
2009-05-22 15:42:51 +04:00
|
|
|
# unintended behaviour:
|
|
|
|
self.assertNotEqual('an_author', tip.user())
|
2010-10-10 01:20:52 +04:00
|
|
|
self.assertEqual('(no author)', tip.user().rsplit('@', 1)[0])
|
2009-05-13 19:22:18 +04:00
|
|
|
finally:
|
2012-04-12 17:39:17 +04:00
|
|
|
if sys.version_info >= (2,6):
|
|
|
|
svnserve.kill()
|
2012-05-17 17:24:54 +04:00
|
|
|
else:
|
2012-04-12 17:39:17 +04:00
|
|
|
test_util.kill_process(svnserve)
|
2009-03-29 01:50:00 +03:00
|
|
|
|
2010-07-28 16:47:44 +04:00
|
|
|
def test_push_over_svnserve(self):
|
|
|
|
self.internal_push_over_svnserve()
|
|
|
|
|
|
|
|
def test_push_over_svnserve_with_subdir(self):
|
|
|
|
self.internal_push_over_svnserve(subdir='///branches////the_branch/////')
|
|
|
|
|
2008-11-01 20:23:07 +03:00
|
|
|
def test_push_to_default(self, commit=True):
|
|
|
|
repo = self.repo
|
|
|
|
old_tip = repo['tip'].node()
|
|
|
|
expected_parent = repo['default'].node()
|
|
|
|
def file_callback(repo, memctx, path):
|
|
|
|
if path == 'adding_file':
|
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='foo',
|
|
|
|
islink=False,
|
|
|
|
isexec=False,
|
|
|
|
copied=False)
|
2010-01-26 19:36:13 +03:00
|
|
|
raise IOError(errno.EINVAL, 'Invalid operation: ' + path)
|
2008-11-01 20:23:07 +03:00
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'automated test',
|
|
|
|
['adding_file'],
|
|
|
|
file_callback,
|
|
|
|
'an_author',
|
|
|
|
'2008-10-07 20:59:48 -0500',
|
2011-10-12 11:35:25 +04:00
|
|
|
{'branch': 'default', })
|
2008-11-01 20:23:07 +03:00
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
if not commit:
|
|
|
|
return # some tests use this test as an extended setup.
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-01 20:23:07 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), old_tip)
|
2008-12-23 06:21:11 +03:00
|
|
|
self.assertEqual(node.hex(tip.parents()[0].node()),
|
|
|
|
node.hex(expected_parent))
|
2008-11-01 20:23:07 +03:00
|
|
|
self.assertEqual(tip['adding_file'].data(), 'foo')
|
|
|
|
self.assertEqual(tip.branch(), 'default')
|
2008-10-08 07:13:14 +04:00
|
|
|
|
2008-12-23 06:21:11 +03:00
|
|
|
def test_push_two_revs_different_local_branch(self):
|
|
|
|
def filectxfn(repo, memctx, path):
|
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data=path,
|
|
|
|
islink=False,
|
|
|
|
isexec=False,
|
|
|
|
copied=False)
|
|
|
|
oldtiphash = self.repo['default'].node()
|
|
|
|
ctx = context.memctx(self.repo,
|
2011-10-12 11:35:25 +04:00
|
|
|
(self.repo[0].node(), revlog.nullid,),
|
2008-12-23 06:21:11 +03:00
|
|
|
'automated test',
|
|
|
|
['gamma', ],
|
|
|
|
filectxfn,
|
|
|
|
'testy',
|
|
|
|
'2008-12-21 16:32:00 -0500',
|
|
|
|
{'branch': 'localbranch', })
|
|
|
|
newhash = self.repo.commitctx(ctx)
|
|
|
|
ctx = context.memctx(self.repo,
|
|
|
|
(newhash, revlog.nullid),
|
|
|
|
'automated test2',
|
|
|
|
['delta', ],
|
|
|
|
filectxfn,
|
|
|
|
'testy',
|
|
|
|
'2008-12-21 16:32:00 -0500',
|
|
|
|
{'branch': 'localbranch', })
|
|
|
|
newhash = self.repo.commitctx(ctx)
|
|
|
|
repo = self.repo
|
|
|
|
hg.update(repo, newhash)
|
2009-05-15 21:18:43 +04:00
|
|
|
commands.push(repo.ui, repo)
|
2008-12-23 06:21:11 +03:00
|
|
|
self.assertEqual(self.repo['tip'].parents()[0].parents()[0].node(), oldtiphash)
|
|
|
|
self.assertEqual(self.repo['tip'].files(), ['delta', ])
|
|
|
|
self.assertEqual(self.repo['tip'].manifest().keys(),
|
|
|
|
['alpha', 'beta', 'gamma', 'delta'])
|
|
|
|
|
2008-11-01 20:23:07 +03:00
|
|
|
def test_push_two_revs(self):
|
|
|
|
# set up some work for us
|
|
|
|
self.test_push_to_default(commit=False)
|
|
|
|
repo = self.repo
|
|
|
|
old_tip = repo['tip'].node()
|
|
|
|
expected_parent = repo['tip'].parents()[0].node()
|
|
|
|
def file_callback(repo, memctx, path):
|
|
|
|
if path == 'adding_file2':
|
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='foo2',
|
|
|
|
islink=False,
|
|
|
|
isexec=False,
|
|
|
|
copied=False)
|
2010-01-26 19:36:13 +03:00
|
|
|
raise IOError(errno.EINVAL, 'Invalid operation: ' + path)
|
2008-11-01 20:23:07 +03:00
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'automated test',
|
|
|
|
['adding_file2'],
|
|
|
|
file_callback,
|
|
|
|
'an_author',
|
|
|
|
'2008-10-07 20:59:48 -0500',
|
2011-10-12 11:35:25 +04:00
|
|
|
{'branch': 'default', })
|
2008-11-01 20:23:07 +03:00
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-01 20:23:07 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), old_tip)
|
|
|
|
self.assertNotEqual(tip.parents()[0].node(), old_tip)
|
|
|
|
self.assertEqual(tip.parents()[0].parents()[0].node(), expected_parent)
|
|
|
|
self.assertEqual(tip['adding_file2'].data(), 'foo2')
|
|
|
|
self.assertEqual(tip['adding_file'].data(), 'foo')
|
|
|
|
self.assertEqual(tip.parents()[0]['adding_file'].data(), 'foo')
|
|
|
|
try:
|
|
|
|
self.assertEqual(tip.parents()[0]['adding_file2'].data(), 'foo')
|
|
|
|
assert False, "this is impossible, adding_file2 should not be in this manifest."
|
|
|
|
except revlog.LookupError, e:
|
|
|
|
pass
|
|
|
|
self.assertEqual(tip.branch(), 'default')
|
2008-10-30 05:15:36 +03:00
|
|
|
|
2009-05-28 06:40:58 +04:00
|
|
|
def test_push_to_branch(self, push=True):
|
2008-11-01 20:23:07 +03:00
|
|
|
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)
|
2010-01-26 19:36:13 +03:00
|
|
|
raise IOError(errno.EINVAL, 'Invalid operation: ' + path)
|
2008-11-01 20:23:07 +03:00
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['the_branch'].node(), node.nullid),
|
|
|
|
'automated test',
|
|
|
|
['adding_file'],
|
|
|
|
file_callback,
|
|
|
|
'an_author',
|
|
|
|
'2008-10-07 20:59:48 -0500',
|
2011-10-12 11:35:25 +04:00
|
|
|
{'branch': 'the_branch', })
|
2008-11-01 20:23:07 +03:00
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2009-05-28 06:40:58 +04:00
|
|
|
if push:
|
|
|
|
self.pushrevisions()
|
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), new_hash)
|
|
|
|
self.assertEqual(tip['adding_file'].data(), 'foo')
|
|
|
|
self.assertEqual(tip.branch(), 'the_branch')
|
|
|
|
|
2010-06-28 06:14:36 +04:00
|
|
|
def test_push_to_non_tip(self):
|
2009-05-28 06:40:58 +04:00
|
|
|
self.test_push_to_branch(push=False)
|
|
|
|
wc2path = self.wc_path + '_clone'
|
|
|
|
u = self.repo.ui
|
2011-06-15 16:44:14 +04:00
|
|
|
test_util.hgclone(self.repo.ui, self.wc_path, wc2path, update=False)
|
2010-06-28 06:18:47 +04:00
|
|
|
res = self.pushrevisions()
|
|
|
|
self.assertEqual(0, res)
|
2009-05-28 06:40:58 +04:00
|
|
|
oldf = open(os.path.join(self.wc_path, '.hg', 'hgrc'))
|
|
|
|
hgrc = oldf.read()
|
|
|
|
oldf.close()
|
|
|
|
shutil.rmtree(self.wc_path)
|
2011-06-15 16:44:14 +04:00
|
|
|
test_util.hgclone(u, wc2path, self.wc_path, update=False)
|
2009-05-28 06:40:58 +04:00
|
|
|
oldf = open(os.path.join(self.wc_path, '.hg', 'hgrc'), 'w')
|
|
|
|
oldf.write(hgrc)
|
|
|
|
oldf.close()
|
|
|
|
|
|
|
|
# do a commit here
|
2011-10-12 11:35:25 +04:00
|
|
|
self.commitchanges([('foobaz', 'foobaz', 'This file is added on default.',),
|
2009-05-28 06:40:58 +04:00
|
|
|
],
|
|
|
|
parent='default',
|
|
|
|
message='commit to default')
|
|
|
|
from hgsubversion import svncommands
|
|
|
|
svncommands.rebuildmeta(u,
|
|
|
|
self.repo,
|
|
|
|
args=[test_util.fileurl(self.repo_path)])
|
|
|
|
|
|
|
|
|
|
|
|
hg.update(self.repo, self.repo['tip'].node())
|
|
|
|
oldnode = self.repo['tip'].hex()
|
|
|
|
self.pushrevisions(expected_extra_back=1)
|
|
|
|
self.assertNotEqual(oldnode, self.repo['tip'].hex(), 'Revision was not pushed.')
|
2008-10-30 05:15:36 +03:00
|
|
|
|
2008-11-01 20:23:07 +03:00
|
|
|
def test_delete_file(self):
|
|
|
|
repo = self.repo
|
|
|
|
def file_callback(repo, memctx, path):
|
2010-02-14 23:04:56 +03:00
|
|
|
raise IOError(errno.ENOENT, '%s is deleted' % path)
|
2008-11-01 20:23:07 +03:00
|
|
|
old_files = set(repo['default'].manifest().keys())
|
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'automated test',
|
|
|
|
['alpha'],
|
|
|
|
file_callback,
|
|
|
|
'an author',
|
|
|
|
'2008-10-29 21:26:00 -0500',
|
|
|
|
{'branch': 'default', })
|
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-01 20:23:07 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertEqual(old_files,
|
|
|
|
set(tip.manifest().keys() + ['alpha']))
|
|
|
|
self.assert_('alpha' not in tip.manifest())
|
2008-10-30 05:15:36 +03:00
|
|
|
|
2008-11-01 20:23:07 +03:00
|
|
|
def test_push_executable_file(self):
|
|
|
|
self.test_push_to_default(commit=True)
|
|
|
|
repo = self.repo
|
|
|
|
def file_callback(repo, memctx, path):
|
|
|
|
if path == 'gamma':
|
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='foo',
|
|
|
|
islink=False,
|
|
|
|
isexec=True,
|
|
|
|
copied=False)
|
2010-01-26 19:36:13 +03:00
|
|
|
raise IOError(errno.EINVAL, 'Invalid operation: ' + path)
|
2008-11-01 20:23:07 +03:00
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['tip'].node(), node.nullid),
|
|
|
|
'message',
|
|
|
|
['gamma', ],
|
|
|
|
file_callback,
|
|
|
|
'author',
|
|
|
|
'2008-10-29 21:26:00 -0500',
|
|
|
|
{'branch': 'default', })
|
|
|
|
new_hash = repo.commitctx(ctx)
|
2009-04-11 07:38:29 +04:00
|
|
|
hg.clean(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-01 20:23:07 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), new_hash)
|
2009-04-11 07:38:29 +04:00
|
|
|
self.assert_('@' in self.repo['tip'].user())
|
2008-11-01 20:23:07 +03:00
|
|
|
self.assertEqual(tip['gamma'].flags(), 'x')
|
|
|
|
self.assertEqual(tip['gamma'].data(), 'foo')
|
|
|
|
self.assertEqual([x for x in tip.manifest().keys() if 'x' not in
|
|
|
|
tip[x].flags()], ['alpha', 'beta', 'adding_file', ])
|
2008-10-30 06:58:52 +03:00
|
|
|
|
2008-11-01 20:23:07 +03:00
|
|
|
def test_push_symlink_file(self):
|
|
|
|
self.test_push_to_default(commit=True)
|
|
|
|
repo = self.repo
|
|
|
|
def file_callback(repo, memctx, path):
|
|
|
|
if path == 'gamma':
|
2008-10-30 06:58:52 +03:00
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='foo',
|
2008-11-01 20:23:07 +03:00
|
|
|
islink=True,
|
|
|
|
isexec=False,
|
2008-10-30 06:58:52 +03:00
|
|
|
copied=False)
|
2010-01-26 19:36:13 +03:00
|
|
|
raise IOError(errno.EINVAL, 'Invalid operation: ' + path)
|
2008-11-01 20:23:07 +03:00
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['tip'].node(), node.nullid),
|
|
|
|
'message',
|
|
|
|
['gamma', ],
|
|
|
|
file_callback,
|
|
|
|
'author',
|
|
|
|
'2008-10-29 21:26:00 -0500',
|
|
|
|
{'branch': 'default', })
|
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-01 20:23:07 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), new_hash)
|
|
|
|
self.assertEqual(tip['gamma'].flags(), 'l')
|
|
|
|
self.assertEqual(tip['gamma'].data(), 'foo')
|
|
|
|
self.assertEqual([x for x in tip.manifest().keys() if 'l' not in
|
|
|
|
tip[x].flags()], ['alpha', 'beta', 'adding_file', ])
|
|
|
|
|
2008-11-06 18:07:13 +03:00
|
|
|
def test_push_existing_file_newly_symlink(self):
|
|
|
|
self.test_push_existing_file_newly_execute(execute=False,
|
|
|
|
link=True,
|
|
|
|
expected_flags='l')
|
|
|
|
|
2008-11-01 20:23:07 +03:00
|
|
|
def test_push_existing_file_newly_execute(self, execute=True,
|
|
|
|
link=False, expected_flags='x'):
|
|
|
|
self.test_push_to_default()
|
|
|
|
repo = self.repo
|
|
|
|
def file_callback(repo, memctx, path):
|
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='foo',
|
|
|
|
islink=link,
|
|
|
|
isexec=execute,
|
|
|
|
copied=False)
|
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'message',
|
|
|
|
['alpha', ],
|
|
|
|
file_callback,
|
|
|
|
'author',
|
|
|
|
'2008-1-1 00:00:00 -0500',
|
|
|
|
{'branch': 'default', })
|
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-01 20:23:07 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), new_hash)
|
|
|
|
self.assertEqual(tip['alpha'].data(), 'foo')
|
|
|
|
self.assertEqual(tip.parents()[0]['alpha'].flags(), '')
|
|
|
|
self.assertEqual(tip['alpha'].flags(), expected_flags)
|
|
|
|
# while we're here, double check pushing an already-executable file
|
|
|
|
# works
|
|
|
|
repo = self.repo
|
2008-11-22 01:21:19 +03:00
|
|
|
def file_callback2(repo, memctx, path):
|
2008-11-01 20:23:07 +03:00
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='bar',
|
|
|
|
islink=link,
|
|
|
|
isexec=execute,
|
|
|
|
copied=False)
|
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'message',
|
|
|
|
['alpha', ],
|
2008-11-22 01:21:19 +03:00
|
|
|
file_callback2,
|
2008-11-01 20:23:07 +03:00
|
|
|
'author',
|
|
|
|
'2008-1-1 00:00:00 -0500',
|
|
|
|
{'branch': 'default', })
|
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-01 20:23:07 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), new_hash)
|
|
|
|
self.assertEqual(tip['alpha'].data(), 'bar')
|
|
|
|
self.assertEqual(tip.parents()[0]['alpha'].flags(), expected_flags)
|
|
|
|
self.assertEqual(tip['alpha'].flags(), expected_flags)
|
2008-11-06 18:24:33 +03:00
|
|
|
# now test removing the property entirely
|
|
|
|
repo = self.repo
|
2008-11-22 01:21:19 +03:00
|
|
|
def file_callback3(repo, memctx, path):
|
2008-11-06 18:24:33 +03:00
|
|
|
return context.memfilectx(path=path,
|
|
|
|
data='bar',
|
|
|
|
islink=False,
|
|
|
|
isexec=False,
|
|
|
|
copied=False)
|
|
|
|
ctx = context.memctx(repo,
|
|
|
|
(repo['default'].node(), node.nullid),
|
|
|
|
'message',
|
|
|
|
['alpha', ],
|
2008-11-22 01:21:19 +03:00
|
|
|
file_callback3,
|
2008-11-06 18:24:33 +03:00
|
|
|
'author',
|
|
|
|
'2008-01-01 00:00:00 -0500',
|
|
|
|
{'branch': 'default', })
|
|
|
|
new_hash = repo.commitctx(ctx)
|
|
|
|
hg.update(repo, repo['tip'].node())
|
2008-11-10 03:08:35 +03:00
|
|
|
self.pushrevisions()
|
2008-11-06 18:24:33 +03:00
|
|
|
tip = self.repo['tip']
|
|
|
|
self.assertNotEqual(tip.node(), new_hash)
|
|
|
|
self.assertEqual(tip['alpha'].data(), 'bar')
|
|
|
|
self.assertEqual(tip.parents()[0]['alpha'].flags(), expected_flags)
|
|
|
|
self.assertEqual(tip['alpha'].flags(), '')
|
2008-10-30 06:58:52 +03:00
|
|
|
|
2009-04-25 05:31:17 +04:00
|
|
|
def test_push_outdated_base_text(self):
|
|
|
|
self.test_push_two_revs()
|
2011-10-12 11:35:25 +04:00
|
|
|
changes = [('adding_file', 'adding_file', 'different_content',),
|
2009-04-25 05:31:17 +04:00
|
|
|
]
|
2010-09-08 12:42:53 +04:00
|
|
|
par = self.repo['tip'].rev()
|
|
|
|
self.commitchanges(changes, parent=par)
|
2009-04-25 05:31:17 +04:00
|
|
|
self.pushrevisions()
|
|
|
|
changes = [('adding_file', 'adding_file',
|
2011-10-12 11:35:25 +04:00
|
|
|
'even_more different_content',),
|
2009-04-25 05:31:17 +04:00
|
|
|
]
|
2010-09-08 12:42:53 +04:00
|
|
|
self.commitchanges(changes, parent=par)
|
2009-04-25 05:31:17 +04:00
|
|
|
try:
|
|
|
|
self.pushrevisions()
|
|
|
|
assert False, 'This should have aborted!'
|
|
|
|
except hgutil.Abort, e:
|
|
|
|
self.assertEqual(e.args[0],
|
2010-02-07 17:56:25 +03:00
|
|
|
'Outgoing changesets parent is not at subversion '
|
|
|
|
'HEAD\n'
|
|
|
|
'(pull again and rebase on a newer revision)')
|
2012-05-17 17:24:54 +04:00
|
|
|
# verify that any pending transactions on the server got cleaned up
|
|
|
|
self.assertEqual([], os.listdir(
|
|
|
|
os.path.join(self.tmpdir, 'testrepo-1', 'db', 'transactions')))
|
2008-10-08 07:13:14 +04:00
|
|
|
|
2012-09-09 16:54:43 +04:00
|
|
|
def test_push_encoding(self):
|
|
|
|
self.test_push_two_revs()
|
|
|
|
# Writing then rebasing UTF-8 filenames in a cp1252 windows console
|
|
|
|
# used to fail because hg internal encoding was being changed during
|
|
|
|
# the interactions with subversion, *and during the rebase*, which
|
|
|
|
# confused the dirstate and made it believe the file was deleted.
|
|
|
|
fn = 'pi\xc3\xa8ce/test'
|
|
|
|
changes = [(fn, fn, 'a')]
|
|
|
|
par = self.repo['tip'].rev()
|
|
|
|
self.commitchanges(changes, parent=par)
|
|
|
|
self.pushrevisions()
|
|
|
|
|
2012-09-09 18:12:28 +04:00
|
|
|
def test_push_emptying_changeset(self):
|
|
|
|
r = self.repo['tip']
|
|
|
|
changes = [
|
|
|
|
('alpha', None, None),
|
|
|
|
('beta', None, None),
|
|
|
|
]
|
|
|
|
parent = self.repo['tip'].rev()
|
|
|
|
self.commitchanges(changes, parent=parent)
|
|
|
|
self.pushrevisions()
|
|
|
|
self.assertEqual({}, self.repo['tip'].manifest())
|
|
|
|
|
|
|
|
# Try to re-add a file after emptying the branch
|
|
|
|
changes = [
|
|
|
|
('alpha', 'alpha', 'alpha'),
|
|
|
|
]
|
|
|
|
self.commitchanges(changes, parent=self.repo['tip'].rev())
|
|
|
|
self.pushrevisions()
|
|
|
|
self.assertEqual(['alpha'], list(self.repo['tip'].manifest()))
|
|
|
|
|
2008-10-08 07:13:14 +04:00
|
|
|
def suite():
|
2009-05-13 19:22:18 +04:00
|
|
|
test_classes = [PushTests, ]
|
2011-10-12 11:50:47 +04:00
|
|
|
all_tests = []
|
2008-10-30 05:15:36 +03:00
|
|
|
# This is the quickest hack I could come up with to load all the tests from
|
|
|
|
# both classes. Would love a patch that simplifies this without adding
|
|
|
|
# dependencies.
|
|
|
|
for tc in test_classes:
|
|
|
|
for attr in dir(tc):
|
|
|
|
if attr.startswith('test_'):
|
2011-10-12 11:50:47 +04:00
|
|
|
all_tests.append(tc(attr))
|
|
|
|
return unittest.TestSuite(all_tests)
|