summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qutebrowser/browser/history.py14
-rw-r--r--qutebrowser/misc/sql.py7
-rw-r--r--tests/helpers/stubs.py5
-rw-r--r--tests/unit/browser/test_history.py42
-rw-r--r--tests/unit/misc/test_sql.py5
5 files changed, 51 insertions, 22 deletions
diff --git a/qutebrowser/browser/history.py b/qutebrowser/browser/history.py
index 8ce319cba..ef4650a35 100644
--- a/qutebrowser/browser/history.py
+++ b/qutebrowser/browser/history.py
@@ -88,6 +88,7 @@ class CompletionMetaInfo(sql.SqlTable):
KEYS = {
'excluded_patterns': '',
+ 'force_rebuild': False,
}
def __init__(self, parent=None):
@@ -95,8 +96,6 @@ class CompletionMetaInfo(sql.SqlTable):
constraints={'key': 'PRIMARY KEY'})
if sql.user_version_changed():
self._init_default_values()
- # force_rebuild is not in use anymore
- self.delete('key', 'force_rebuild', optional=True)
def _check_key(self, key):
if key not in self.KEYS:
@@ -165,7 +164,7 @@ class WebHistory(sql.SqlTable):
self.completion = CompletionHistory(parent=self)
self.metainfo = CompletionMetaInfo(parent=self)
- rebuild_completion = False
+ rebuild_completion = self.metainfo['force_rebuild']
if sql.user_version_changed():
# If the DB user version changed, run a full cleanup and rebuild the
@@ -186,8 +185,8 @@ class WebHistory(sql.SqlTable):
self.metainfo['excluded_patterns'] = patterns
rebuild_completion = True
- if rebuild_completion and self.completion:
- # If no completion history exists, we don't need to spawn a dialog for
+ if rebuild_completion and self:
+ # If no history exists, we don't need to spawn a dialog for
# cleaning it up.
self._rebuild_completion()
@@ -259,6 +258,10 @@ class WebHistory(sql.SqlTable):
log.sql.debug(f"Cleanup removed {entries.rows_affected()} items")
def _rebuild_completion(self):
+ # If this process was interrupted, make sure we trigger a rebuild again
+ # at the next start.
+ self.metainfo['force_rebuild'] = True
+
data: Mapping[str, MutableSequence[str]] = {
'url': [],
'title': [],
@@ -305,6 +308,7 @@ class WebHistory(sql.SqlTable):
QApplication.processEvents()
self._progress.finish()
+ self.metainfo['force_rebuild'] = False
def get_recent(self):
"""Get the most recent history entries."""
diff --git a/qutebrowser/misc/sql.py b/qutebrowser/misc/sql.py
index 774f3ebb0..7a3626f6e 100644
--- a/qutebrowser/misc/sql.py
+++ b/qutebrowser/misc/sql.py
@@ -66,7 +66,7 @@ class UserVersion:
_db_user_version = None # The user version we got from the database
-_USER_VERSION = UserVersion(0, 3) # The current / newest user version
+_USER_VERSION = UserVersion(0, 4) # The current / newest user version
def user_version_changed():
@@ -409,13 +409,12 @@ class SqlTable(QObject):
q.run()
return q.query.next()
- def delete(self, field, value, *, optional=False):
+ def delete(self, field, value):
"""Remove all rows for which `field` equals `value`.
Args:
field: Field to use as the key.
value: Key value to delete.
- optional: If set, non-existent values are ignored.
Return:
The number of rows deleted.
@@ -423,8 +422,6 @@ class SqlTable(QObject):
q = Query(f"DELETE FROM {self._name} where {field} = :val")
q.run(val=value)
if not q.rows_affected():
- if optional:
- return
raise KeyError('No row with {} = "{}"'.format(field, value))
self.changed.emit()
diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py
index c1ccdcf8b..de5cd981f 100644
--- a/tests/helpers/stubs.py
+++ b/tests/helpers/stubs.py
@@ -623,10 +623,11 @@ class FakeHistoryProgress:
"""Fake for a WebHistoryProgress object."""
- def __init__(self):
+ def __init__(self, *, raise_on_tick=False):
self._started = False
self._finished = False
self._value = 0
+ self._raise_on_tick = raise_on_tick
def start(self, _text):
self._started = True
@@ -635,6 +636,8 @@ class FakeHistoryProgress:
pass
def tick(self):
+ if self._raise_on_tick:
+ raise Exception('tick-tock')
self._value += 1
def finish(self):
diff --git a/tests/unit/browser/test_history.py b/tests/unit/browser/test_history.py
index 9e3bd0519..c032f6265 100644
--- a/tests/unit/browser/test_history.py
+++ b/tests/unit/browser/test_history.py
@@ -392,6 +392,25 @@ class TestRebuild:
('example.com/1', '', 1),
('example.com/2', '', 2),
]
+ assert not hist3.metainfo['force_rebuild']
+
+ def test_force_rebuild(self, web_history, stubs):
+ """Ensure that completion is regenerated if we force a rebuild."""
+ web_history.add_url(QUrl('example.com/1'), redirect=False, atime=1)
+ web_history.add_url(QUrl('example.com/2'), redirect=False, atime=2)
+ web_history.completion.delete('url', 'example.com/2')
+
+ hist2 = history.WebHistory(progress=stubs.FakeHistoryProgress())
+ # User version always changes, so this won't work
+ # assert list(hist2.completion) == [('example.com/1', '', 1)]
+ hist2.metainfo['force_rebuild'] = True
+
+ hist3 = history.WebHistory(progress=stubs.FakeHistoryProgress())
+ assert list(hist3.completion) == [
+ ('example.com/1', '', 1),
+ ('example.com/2', '', 2),
+ ]
+ assert not hist3.metainfo['force_rebuild']
def test_exclude(self, config_stub, web_history, stubs):
"""Ensure that patterns in completion.web_history.exclude are ignored.
@@ -443,6 +462,23 @@ class TestRebuild:
assert progress._started
assert progress._finished
+ def test_interrupted(self, stubs, web_history, monkeypatch):
+ """If we interrupt the rebuilding process, force_rebuild should still be set."""
+ web_history.add_url(QUrl('example.com/1'), redirect=False, atime=1)
+ progress = stubs.FakeHistoryProgress(raise_on_tick=True)
+
+ # Trigger a completion rebuild
+ monkeypatch.setattr(sql, 'user_version_changed', lambda: True)
+
+ with pytest.raises(Exception, match='tick-tock'):
+ history.WebHistory(progress=progress)
+
+ assert web_history.metainfo['force_rebuild']
+
+ # If we now try again, we should get another rebuild. But due to user_version
+ # always changing, we can't test this at the moment (see the FIXME in the
+ # docstring for details)
+
class TestCompletionMetaInfo:
@@ -466,12 +502,6 @@ class TestCompletionMetaInfo:
def test_contains(self, metainfo):
assert 'excluded_patterns' in metainfo
- def test_delete_old_key(self, monkeypatch, metainfo):
- metainfo.insert({'key': 'force_rebuild', 'value': False})
- info2 = history.CompletionMetaInfo()
- monkeypatch.setitem(info2.KEYS, 'force_rebuild', False)
- assert 'force_rebuild' not in info2
-
def test_modify(self, metainfo):
assert not metainfo['excluded_patterns']
value = 'https://example.com/'
diff --git a/tests/unit/misc/test_sql.py b/tests/unit/misc/test_sql.py
index 211280a6b..92bede511 100644
--- a/tests/unit/misc/test_sql.py
+++ b/tests/unit/misc/test_sql.py
@@ -227,11 +227,6 @@ def test_delete(qtbot):
assert not list(table)
-def test_delete_optional(qtbot):
- table = sql.SqlTable('Foo', ['name', 'val'])
- table.delete('name', 'doesnotexist', optional=True)
-
-
def test_len():
table = sql.SqlTable('Foo', ['name', 'val', 'lucky'])
assert len(table) == 0