# HG changeset patch # User Augie Fackler # Date 1249736484 18000 # Node ID c2d0e738c8993e266e56a0590862c0a1796d2163 # Parent 3855865ba53d9ca75d908e6aa42a0d0fbed1305f# Parent 37718f514acb3d1879897a701a376628b668eee5 Merge win32 fixes 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 @@ -131,7 +131,8 @@ class PushTests(test_util.TestBase): self.assertNotEqual('an_author', tip.user()) self.assertEqual('None', tip.user().rsplit('@', 1)[0]) finally: - os.kill(self.svnserve_pid, 9) + # TODO: use svnserve.kill() in Python >2.5 + test_util.kill_process(svnserve) def test_push_to_default(self, commit=True): repo = self.repo diff --git a/tests/test_svnwrap.py b/tests/test_svnwrap.py --- a/tests/test_svnwrap.py +++ b/tests/test_svnwrap.py @@ -9,23 +9,33 @@ import test_util from hgsubversion import svnwrap +import os +import stat +def force_rm(path): + os.chmod( + path, + os.stat(path).st_mode | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH + ) + os.remove(path) + class TestBasicRepoLayout(unittest.TestCase): def setUp(self): self.tmpdir = tempfile.mkdtemp('svnwrap_test') self.repo_path = '%s/testrepo' % self.tmpdir - os.spawnvp(os.P_WAIT, 'svnadmin', ['svnadmin', 'create', - self.repo_path,]) + subprocess.call(['svnadmin', 'create', self.repo_path,]) inp = open(os.path.join(os.path.dirname(__file__), 'fixtures', 'project_root_at_repo_root.svndump')) proc = subprocess.call(['svnadmin', 'load', self.repo_path,], - stdin=inp, close_fds=True, + stdin=inp, + close_fds=test_util.canCloseFds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) assert proc == 0 - self.repo = svnwrap.SubversionRepo('file://%s' % self.repo_path) + self.repo = svnwrap.SubversionRepo(test_util.fileurl(self.repo_path)) def tearDown(self): - shutil.rmtree(self.tmpdir) + del self.repo + shutil.rmtree(self.tmpdir, onerror=lambda func, path, e: force_rm(path)) def test_num_revs(self): @@ -59,17 +69,19 @@ class TestRootAsSubdirOfRepo(TestBasicRe def setUp(self): self.tmpdir = tempfile.mkdtemp('svnwrap_test') self.repo_path = '%s/testrepo' % self.tmpdir - os.spawnvp(os.P_WAIT, 'svnadmin', ['svnadmin', 'create', - self.repo_path,]) + subprocess.call(['svnadmin', 'create', self.repo_path,]) inp = open(os.path.join(os.path.dirname(__file__), 'fixtures', 'project_root_not_repo_root.svndump')) ret = subprocess.call(['svnadmin', 'load', self.repo_path,], - stdin=inp, close_fds=True, + stdin=inp, + close_fds=test_util.canCloseFds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) assert ret == 0 - self.repo = svnwrap.SubversionRepo('file://%s/dummyproj' % - self.repo_path) + self.repo = svnwrap.SubversionRepo(test_util.fileurl( + self.repo_path + '/dummyproj' + )) + def suite(): all = [unittest.TestLoader().loadTestsFromTestCase(TestBasicRepoLayout), unittest.TestLoader().loadTestsFromTestCase(TestRootAsSubdirOfRepo)] diff --git a/tests/test_util.py b/tests/test_util.py --- a/tests/test_util.py +++ b/tests/test_util.py @@ -19,6 +19,57 @@ from mercurial import ui from hgsubversion import util +import sys +# Documentation for Subprocess.Popen() says: +# "Note that on Windows, you cannot set close_fds to true and +# also redirect the standard handles by setting stdin, stdout or +# stderr." +canCloseFds='win32' not in sys.platform + +if not 'win32' in sys.platform: + def kill_process(popen_obj): + os.kill(popen_obj.pid, 9) +else: + import ctypes + from ctypes.wintypes import BOOL, DWORD, HANDLE, UINT + + def win_status_check(result, func, args): + if result == 0: + raise ctypes.WinError() + return args + + def WINAPI(returns, func, *params): + assert len(params) % 2 == 0 + + func.argtypes = tuple(params[0::2]) + func.resvalue = returns + func.errcheck = win_status_check + + return func + + # dwDesiredAccess + PROCESS_TERMINATE = 0x0001 + + OpenProcess = WINAPI(HANDLE, ctypes.windll.kernel32.OpenProcess, + DWORD, 'dwDesiredAccess', + BOOL, 'bInheritHandle', + DWORD, 'dwProcessId', + ) + + CloseHandle = WINAPI(BOOL, ctypes.windll.kernel32.CloseHandle, + HANDLE, 'hObject' + ) + + TerminateProcess = WINAPI(BOOL, ctypes.windll.kernel32.TerminateProcess, + HANDLE, 'hProcess', + UINT, 'uExitCode' + ) + + def kill_process(popen_obj): + phnd = OpenProcess(PROCESS_TERMINATE, False, popen_obj.pid) + TerminateProcess(phnd, 1) + CloseHandle(phnd) + # Fixtures that need to be pulled at a subdirectory of the repo path subdir = {'truncatedhistory.svndump': '/project2', 'fetch_missing_files_subdir.svndump': '/foo',