blob: 343347026f138e5689f072dde06c4c60d5fd37f8 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import atexit
import os
import signal
import socket
import sys
import threading
from cStringIO import StringIO
from subprocess import check_call, Popen
from textwrap import dedent
def capture_terminal(f, *args, **kwargs):
"""Run f() with sys.stdout and sys.stderr reassigned to buffered pipes."""
old_std = (sys.stdout, sys.stderr)
(out_buf, err_buf) = (StringIO(), StringIO())
(out_pipe, err_pipe) = (os.pipe(), os.pipe())
def _thr_main(fd, buf):
with os.fdopen(fd) as fh:
buf.write(fh.read())
(out_thread, err_thread) = (
threading.Thread(target=_thr_main, args=(out_pipe[0], out_buf)),
threading.Thread(target=_thr_main, args=(err_pipe[0], err_buf)))
out_thread.start()
err_thread.start()
sys.stdout = os.fdopen(out_pipe[1], 'w')
sys.stderr = os.fdopen(err_pipe[1], 'w')
try:
result = f(*args, **kwargs)
except Exception as e:
sys.excepthook(*sys.exc_info())
result = e
sys.stdout.close()
sys.stderr.close()
out_thread.join()
err_thread.join()
(sys.stdout, sys.stderr) = old_std
return result, out_buf, err_buf
def find_free_port():
"""Find an avaible port on localhost."""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 0))
port = sock.getsockname()[1]
sock.close()
return port
class LocalGitServer(object):
"""A git server daemon running on localhost."""
def __init__(self, root):
self.root = root
self.port = find_free_port()
self.url = 'git://localhost:%s' % self.port
self.devnull = open(os.devnull, 'w')
os.makedirs(root)
self.proc = Popen(
['git', 'daemon', '--export-all', '--reuseaddr', '--listen=localhost',
'--port=%d' % self.port, '--base-path=%s' % root, root],
stdout=self.devnull, stderr=self.devnull)
def stop(self):
try:
self.proc.terminate()
self.devnull.close()
except Exception:
pass
class LocalSvnServer(object):
"""An svnserve daemon running on localhost."""
def __init__(self, root):
self.root = root
self.pid_file = os.path.join(root, 'svnserve.pid')
self.port = find_free_port()
self.url = 'svn://localhost:%d/svn' % self.port
self.devnull = open(os.devnull, 'w')
os.makedirs(self.root)
check_call(
['svnadmin', 'create', root], stdout=self.devnull, stderr=self.devnull)
with open(os.path.join(root, 'conf', 'svnserve.conf'), 'w') as fh:
fh.write(dedent('''\
[general]
anon-access = write
'''))
check_call(
['svnserve', '-d', '-r', self.root, '--listen-port=%d' % self.port,
'--pid-file=%s' % self.pid_file],
stdout=self.devnull, stderr=self.devnull)
with open(self.pid_file) as fh:
self.pid = int(fh.read().strip())
atexit.register(self.stop)
def stop(self):
try:
if self.pid:
os.kill(self.pid, signal.SIGKILL)
self.pid = None
if self.devnull:
self.devnull.close()
self.devnull = None
except Exception:
pass