parent
aab5411317
commit
54131e9d3e
@ -47,6 +47,9 @@ show it.
|
|||||||
*--cachedir* 'CACHEDIR'::
|
*--cachedir* 'CACHEDIR'::
|
||||||
Set cache directory (empty for no cache storage).
|
Set cache directory (empty for no cache storage).
|
||||||
|
|
||||||
|
*--basedir* 'BASEDIR'::
|
||||||
|
Base directory for all storage. Other --*dir arguments are ignored if this is given.
|
||||||
|
|
||||||
*-V*, *--version*::
|
*-V*, *--version*::
|
||||||
Show version and quit.
|
Show version and quit.
|
||||||
|
|
||||||
|
@ -84,11 +84,11 @@ def run(args):
|
|||||||
objreg.register('signal-handler', signal_handler)
|
objreg.register('signal-handler', signal_handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sent = ipc.send_to_running_instance(args.command)
|
sent = ipc.send_to_running_instance(args)
|
||||||
if sent:
|
if sent:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
log.init.debug("Starting IPC server...")
|
log.init.debug("Starting IPC server...")
|
||||||
server = ipc.IPCServer(qApp)
|
server = ipc.IPCServer(args, qApp)
|
||||||
objreg.register('ipc-server', server)
|
objreg.register('ipc-server', server)
|
||||||
server.got_args.connect(lambda args, cwd:
|
server.got_args.connect(lambda args, cwd:
|
||||||
process_pos_args(args, cwd=cwd, via_ipc=True))
|
process_pos_args(args, cwd=cwd, via_ipc=True))
|
||||||
@ -96,7 +96,7 @@ def run(args):
|
|||||||
# This could be a race condition...
|
# This could be a race condition...
|
||||||
log.init.debug("Got AddressInUseError, trying again.")
|
log.init.debug("Got AddressInUseError, trying again.")
|
||||||
time.sleep(500)
|
time.sleep(500)
|
||||||
sent = ipc.send_to_running_instance(args.command)
|
sent = ipc.send_to_running_instance(args)
|
||||||
if sent:
|
if sent:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
@ -199,7 +199,7 @@ def _process_args(args):
|
|||||||
|
|
||||||
process_pos_args(args.command)
|
process_pos_args(args.command)
|
||||||
_open_startpage()
|
_open_startpage()
|
||||||
_open_quickstart()
|
_open_quickstart(args)
|
||||||
|
|
||||||
|
|
||||||
def _load_session(name):
|
def _load_session(name):
|
||||||
@ -303,8 +303,15 @@ def _open_startpage(win_id=None):
|
|||||||
tabbed_browser.tabopen(url)
|
tabbed_browser.tabopen(url)
|
||||||
|
|
||||||
|
|
||||||
def _open_quickstart():
|
def _open_quickstart(args):
|
||||||
"""Open quickstart if it's the first start."""
|
"""Open quickstart if it's the first start.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: The argparse namespace.
|
||||||
|
"""
|
||||||
|
if args.datadir is not None or args.basedir is not None:
|
||||||
|
# With --datadir or --basedir given, don't open quickstart.
|
||||||
|
return
|
||||||
state_config = objreg.get('state-config')
|
state_config = objreg.get('state-config')
|
||||||
try:
|
try:
|
||||||
quickstart_done = state_config['general']['quickstart-done'] == '1'
|
quickstart_done = state_config['general']['quickstart-done'] == '1'
|
||||||
|
@ -23,6 +23,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
import getpass
|
import getpass
|
||||||
import binascii
|
import binascii
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
|
||||||
from PyQt5.QtNetwork import QLocalSocket, QLocalServer, QAbstractSocket
|
from PyQt5.QtNetwork import QLocalSocket, QLocalServer, QAbstractSocket
|
||||||
@ -31,12 +32,20 @@ from PyQt5.QtWidgets import QMessageBox
|
|||||||
from qutebrowser.utils import log, usertypes
|
from qutebrowser.utils import log, usertypes
|
||||||
|
|
||||||
|
|
||||||
SOCKETNAME = 'qutebrowser-{}'.format(getpass.getuser())
|
|
||||||
CONNECT_TIMEOUT = 100
|
CONNECT_TIMEOUT = 100
|
||||||
WRITE_TIMEOUT = 1000
|
WRITE_TIMEOUT = 1000
|
||||||
READ_TIMEOUT = 5000
|
READ_TIMEOUT = 5000
|
||||||
|
|
||||||
|
|
||||||
|
def _get_socketname(args):
|
||||||
|
"""Get a socketname to use."""
|
||||||
|
parts = ['qutebrowser', getpass.getuser()]
|
||||||
|
if args.basedir is not None:
|
||||||
|
md5 = hashlib.md5(args.basedir.encode('utf-8'))
|
||||||
|
parts.append(md5.hexdigest())
|
||||||
|
return '-'.join(parts)
|
||||||
|
|
||||||
|
|
||||||
class Error(Exception):
|
class Error(Exception):
|
||||||
|
|
||||||
"""Exception raised when there was a problem with IPC."""
|
"""Exception raised when there was a problem with IPC."""
|
||||||
@ -80,6 +89,7 @@ class IPCServer(QObject):
|
|||||||
_timer: A timer to handle timeouts.
|
_timer: A timer to handle timeouts.
|
||||||
_server: A QLocalServer to accept new connections.
|
_server: A QLocalServer to accept new connections.
|
||||||
_socket: The QLocalSocket we're currently connected to.
|
_socket: The QLocalSocket we're currently connected to.
|
||||||
|
_socketname: The socketname to use.
|
||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
got_args: Emitted when there was an IPC connection and arguments were
|
got_args: Emitted when there was an IPC connection and arguments were
|
||||||
@ -88,16 +98,22 @@ class IPCServer(QObject):
|
|||||||
|
|
||||||
got_args = pyqtSignal(list, str)
|
got_args = pyqtSignal(list, str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, args, parent=None):
|
||||||
"""Start the IPC server and listen to commands."""
|
"""Start the IPC server and listen to commands.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: The argparse namespace.
|
||||||
|
parent: The parent to be used.
|
||||||
|
"""
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.ignored = False
|
self.ignored = False
|
||||||
|
self._socketname = _get_socketname(args)
|
||||||
self._remove_server()
|
self._remove_server()
|
||||||
self._timer = usertypes.Timer(self, 'ipc-timeout')
|
self._timer = usertypes.Timer(self, 'ipc-timeout')
|
||||||
self._timer.setInterval(READ_TIMEOUT)
|
self._timer.setInterval(READ_TIMEOUT)
|
||||||
self._timer.timeout.connect(self.on_timeout)
|
self._timer.timeout.connect(self.on_timeout)
|
||||||
self._server = QLocalServer(self)
|
self._server = QLocalServer(self)
|
||||||
ok = self._server.listen(SOCKETNAME)
|
ok = self._server.listen(self._socketname)
|
||||||
if not ok:
|
if not ok:
|
||||||
if self._server.serverError() == QAbstractSocket.AddressInUseError:
|
if self._server.serverError() == QAbstractSocket.AddressInUseError:
|
||||||
raise AddressInUseError(self._server)
|
raise AddressInUseError(self._server)
|
||||||
@ -108,9 +124,10 @@ class IPCServer(QObject):
|
|||||||
|
|
||||||
def _remove_server(self):
|
def _remove_server(self):
|
||||||
"""Remove an existing server."""
|
"""Remove an existing server."""
|
||||||
ok = QLocalServer.removeServer(SOCKETNAME)
|
ok = QLocalServer.removeServer(self._socketname)
|
||||||
if not ok:
|
if not ok:
|
||||||
raise Error("Error while removing server {}!".format(SOCKETNAME))
|
raise Error("Error while removing server {}!".format(
|
||||||
|
self._socketname))
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def on_error(self, error):
|
def on_error(self, error):
|
||||||
@ -223,23 +240,23 @@ def _socket_error(action, socket):
|
|||||||
action, socket.errorString(), socket.error()))
|
action, socket.errorString(), socket.error()))
|
||||||
|
|
||||||
|
|
||||||
def send_to_running_instance(cmdlist):
|
def send_to_running_instance(args):
|
||||||
"""Try to send a commandline to a running instance.
|
"""Try to send a commandline to a running instance.
|
||||||
|
|
||||||
Blocks for CONNECT_TIMEOUT ms.
|
Blocks for CONNECT_TIMEOUT ms.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cmdlist: A list to send (URLs/commands)
|
args: The argparse namespace.
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
True if connecting was successful, False if no connection was made.
|
True if connecting was successful, False if no connection was made.
|
||||||
"""
|
"""
|
||||||
socket = QLocalSocket()
|
socket = QLocalSocket()
|
||||||
socket.connectToServer(SOCKETNAME)
|
socket.connectToServer(_get_socketname(args))
|
||||||
connected = socket.waitForConnected(100)
|
connected = socket.waitForConnected(100)
|
||||||
if connected:
|
if connected:
|
||||||
log.ipc.info("Opening in existing instance")
|
log.ipc.info("Opening in existing instance")
|
||||||
json_data = {'args': cmdlist}
|
json_data = {'args': args.command}
|
||||||
try:
|
try:
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -52,6 +52,8 @@ def get_argparser():
|
|||||||
"no data storage).")
|
"no data storage).")
|
||||||
parser.add_argument('--cachedir', help="Set cache directory (empty for "
|
parser.add_argument('--cachedir', help="Set cache directory (empty for "
|
||||||
"no cache storage).")
|
"no cache storage).")
|
||||||
|
parser.add_argument('--basedir', help="Base directory for all storage. "
|
||||||
|
"Other --*dir arguments are ignored if this is given.")
|
||||||
parser.add_argument('-V', '--version', help="Show version and quit.",
|
parser.add_argument('-V', '--version', help="Show version and quit.",
|
||||||
action='store_true')
|
action='store_true')
|
||||||
parser.add_argument('-s', '--set', help="Set a temporary setting for "
|
parser.add_argument('-s', '--set', help="Set a temporary setting for "
|
||||||
|
@ -84,8 +84,22 @@ def _from_args(typ, args):
|
|||||||
QStandardPaths.DataLocation: 'datadir',
|
QStandardPaths.DataLocation: 'datadir',
|
||||||
QStandardPaths.CacheLocation: 'cachedir',
|
QStandardPaths.CacheLocation: 'cachedir',
|
||||||
}
|
}
|
||||||
|
basedir_suffix = {
|
||||||
|
QStandardPaths.ConfigLocation: 'config',
|
||||||
|
QStandardPaths.DataLocation: 'data',
|
||||||
|
QStandardPaths.CacheLocation: 'cache',
|
||||||
|
QStandardPaths.DownloadLocation: 'download',
|
||||||
|
QStandardPaths.RuntimeLocation: 'runtime',
|
||||||
|
}
|
||||||
|
|
||||||
if args is None:
|
if args is None:
|
||||||
return (False, None)
|
return (False, None)
|
||||||
|
|
||||||
|
if getattr(args, 'basedir', None) is not None:
|
||||||
|
basedir = args.basedir
|
||||||
|
suffix = basedir_suffix[typ]
|
||||||
|
return (True, os.path.join(basedir, suffix))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
argname = typ_to_argparse_arg[typ]
|
argname = typ_to_argparse_arg[typ]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -154,3 +154,13 @@ class TestArguments:
|
|||||||
datadir=testcase.arg)
|
datadir=testcase.arg)
|
||||||
standarddir.init(args)
|
standarddir.init(args)
|
||||||
assert standarddir.data() == testcase.expected
|
assert standarddir.data() == testcase.expected
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('typ', ['config', 'data', 'cache', 'download',
|
||||||
|
'runtime'])
|
||||||
|
def test_basedir(self, tmpdir, typ):
|
||||||
|
"""Test --basedir."""
|
||||||
|
expected = str(tmpdir / typ)
|
||||||
|
args = types.SimpleNamespace(basedir=str(tmpdir))
|
||||||
|
standarddir.init(args)
|
||||||
|
func = getattr(standarddir, typ)
|
||||||
|
assert func() == expected
|
||||||
|
Loading…
Reference in New Issue
Block a user