mirror of
https://github.com/wting/autojump
synced 2024-10-27 20:34:07 +00:00
Fix #123, new installations were not initializing database properly.
Also added unit test coverage to check database initialization, saving, and loading. Unit tests also revealed that migration code was not working properly (starts database from scratch instead of copying existing entries over).
This commit is contained in:
parent
b3c3253e89
commit
b00e0e85e1
25
bin/autojump
25
bin/autojump
@ -81,6 +81,7 @@ class Database:
|
|||||||
else:
|
else:
|
||||||
import math
|
import math
|
||||||
self.data[path] = math.sqrt((self.data[path]**2)+(increment**2))
|
self.data[path] = math.sqrt((self.data[path]**2)+(increment**2))
|
||||||
|
self.save()
|
||||||
|
|
||||||
def decay(self):
|
def decay(self):
|
||||||
"""
|
"""
|
||||||
@ -102,34 +103,34 @@ class Database:
|
|||||||
"""
|
"""
|
||||||
Try to open the database file, recovering from backup if needed.
|
Try to open the database file, recovering from backup if needed.
|
||||||
"""
|
"""
|
||||||
try:
|
if os.path.exists(self.filename):
|
||||||
with open(self.filename, 'r') as aj_file:
|
with open(self.filename, 'r') as f:
|
||||||
for line in aj_file.readlines():
|
for line in f.readlines():
|
||||||
weight, path = line[:-1].split("\t", 1)
|
weight, path = line[:-1].split("\t", 1)
|
||||||
path = decode(path, 'utf-8')
|
path = decode(path, 'utf-8')
|
||||||
self.data[path] = float(weight)
|
self.data[path] = float(weight)
|
||||||
except (IOError, EOFError):
|
elif os.path.exists(self.filename + '.bak'):
|
||||||
if not error_recovery and os.path.exists(self.filename + ".bak"):
|
if not error_recovery:
|
||||||
print('Problem with autojump database,\
|
print('Problem with autojump database,\
|
||||||
trying to recover from backup...', file=sys.stderr)
|
trying to recover from backup...', file=sys.stderr)
|
||||||
shutil.copy(self.filename + '.bak', self.filename)
|
shutil.copy(self.filename + '.bak', self.filename)
|
||||||
return self.load(True)
|
return self.load(True)
|
||||||
else:
|
else:
|
||||||
# TODO: migration code, will be removed in v22+
|
# migration code, autojump_py last used in v17
|
||||||
# autojump_py last used in v17
|
|
||||||
self.filename = get_db_file('autojump_py')
|
self.filename = get_db_file('autojump_py')
|
||||||
if os.path.exists(self.filename):
|
if os.path.exists(self.filename):
|
||||||
try: # fix to get optimised pickle in python < 3
|
try: # fix to get optimised pickle in python < 3
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.filename, 'rb') as aj_file:
|
with open(self.filename, 'rb') as f:
|
||||||
# encoding is only specified for Python 2 compatibility
|
# encoding is only specified for Python 2 compatibility
|
||||||
if sys.version_info[0] > 2:
|
if sys.version_info[0] > 2:
|
||||||
self.data = pickle.load(aj_file, encoding="utf-8")
|
self.data = pickle.load(f, encoding="utf-8")
|
||||||
else:
|
else:
|
||||||
self.data = pickle.load(aj_file)
|
self.data = pickle.load(f)
|
||||||
unicode_dict = {}
|
unicode_dict = {}
|
||||||
for k, v in self.data.items():
|
for k, v in self.data.items():
|
||||||
print(k)
|
print(k)
|
||||||
@ -163,7 +164,8 @@ class Database:
|
|||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""
|
"""
|
||||||
Save database atomically and preserve backup.
|
Save database atomically and preserve backup, creating new database if
|
||||||
|
needed.
|
||||||
"""
|
"""
|
||||||
# check file existence and permissions
|
# check file existence and permissions
|
||||||
if ((not os.path.exists(self.filename)) or
|
if ((not os.path.exists(self.filename)) or
|
||||||
@ -247,7 +249,6 @@ def options():
|
|||||||
if(ARGS.add != os.path.expanduser("~")):
|
if(ARGS.add != os.path.expanduser("~")):
|
||||||
db = Database(DB_FILE)
|
db = Database(DB_FILE)
|
||||||
db.add(decode(ARGS.add))
|
db.add(decode(ARGS.add))
|
||||||
db.save()
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if (ARGS.purge):
|
if (ARGS.purge):
|
||||||
|
@ -6,10 +6,23 @@
|
|||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import autojump
|
import autojump
|
||||||
|
import contextlib
|
||||||
|
import random
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def no_stderr():
|
||||||
|
savestderr = sys.stderr
|
||||||
|
class DevNull(object):
|
||||||
|
def write(self, _): pass
|
||||||
|
sys.stderr = DevNull()
|
||||||
|
yield
|
||||||
|
sys.stderr = savestderr
|
||||||
|
|
||||||
# test suite
|
# test suite
|
||||||
class TestAutojump(unittest.TestCase):
|
class TestAutojump(unittest.TestCase):
|
||||||
|
|
||||||
@ -18,6 +31,8 @@ class TestAutojump(unittest.TestCase):
|
|||||||
self.fd, self.fname = tempfile.mkstemp()
|
self.fd, self.fname = tempfile.mkstemp()
|
||||||
self.db = autojump.Database(self.fname)
|
self.db = autojump.Database(self.fname)
|
||||||
|
|
||||||
|
random.seed()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.remove(self.fname)
|
os.remove(self.fname)
|
||||||
if os.path.isfile(self.fname + ".bak"):
|
if os.path.isfile(self.fname + ".bak"):
|
||||||
@ -42,26 +57,86 @@ class TestAutojump(unittest.TestCase):
|
|||||||
self.db.decay()
|
self.db.decay()
|
||||||
self.assertTrue(self.db.get_weight('/1') < 10)
|
self.assertTrue(self.db.get_weight('/1') < 10)
|
||||||
|
|
||||||
def test_db_load_empty(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_db_load_backup(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_db_load_migrate(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_db_load_existing(self):
|
def test_db_load_existing(self):
|
||||||
self.db = autojump.Database('tests/database.txt')
|
self.db = autojump.Database('tests/database.txt')
|
||||||
self.assertTrue(len(self.db) > 0)
|
self.assertTrue(len(self.db) > 0)
|
||||||
|
|
||||||
|
def test_db_load_empty(self):
|
||||||
|
# setup
|
||||||
|
_, fname = tempfile.mkstemp()
|
||||||
|
db = autojump.Database(fname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# test
|
||||||
|
self.assertEquals(len(self.db), 0)
|
||||||
|
finally:
|
||||||
|
# teardown
|
||||||
|
os.remove(fname)
|
||||||
|
|
||||||
|
def test_db_load_backup(self):
|
||||||
|
# setup
|
||||||
|
fname = '/tmp/autojump_test_db_load_backup_' + str(random.randint(0,32678))
|
||||||
|
db = autojump.Database(fname)
|
||||||
|
db.add('/1')
|
||||||
|
os.rename(fname, fname + '.bak')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# test
|
||||||
|
with no_stderr():
|
||||||
|
db = autojump.Database(fname)
|
||||||
|
self.assertTrue(len(db.data) > 0)
|
||||||
|
self.assertTrue(os.path.isfile(fname))
|
||||||
|
finally:
|
||||||
|
# teardown
|
||||||
|
os.remove(fname)
|
||||||
|
os.remove(fname + '.bak')
|
||||||
|
|
||||||
|
def test_db_load_migrate(self):
|
||||||
|
ORIG_CONFIG_DIR = autojump.CONFIG_DIR
|
||||||
|
try:
|
||||||
|
# setup
|
||||||
|
CONFIG_DIR = '/tmp/autojump_test_db_load_migrate_' + str(random.randint(0,32678))
|
||||||
|
os.mkdir(CONFIG_DIR)
|
||||||
|
autojump.CONFIG_DIR = CONFIG_DIR
|
||||||
|
fname = CONFIG_DIR + '/autojump_py'
|
||||||
|
db = autojump.Database(fname)
|
||||||
|
db.add('/1')
|
||||||
|
shutil.copy(fname, fname + '.bak')
|
||||||
|
db.add('/2')
|
||||||
|
|
||||||
|
# test
|
||||||
|
missing_fname = '/tmp/autojump_test_db_load_missing_' + str(random.randint(0,32678)) + '.txt'
|
||||||
|
db = autojump.Database(missing_fname)
|
||||||
|
|
||||||
|
db.add('/3')
|
||||||
|
self.assertEquals(len(db.data), 3)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# teardown
|
||||||
|
shutil.rmtree(CONFIG_DIR)
|
||||||
|
os.remove(missing_fname)
|
||||||
|
os.remove(missing_fname + '.bak')
|
||||||
|
|
||||||
|
autojump.CONFIG_DIR = ORIG_CONFIG_DIR
|
||||||
|
|
||||||
def test_db_purge(self):
|
def test_db_purge(self):
|
||||||
self.db.add('/1')
|
self.db.add('/1')
|
||||||
self.db.purge()
|
self.db.purge()
|
||||||
self.assertEquals(len(self.db), 0)
|
self.assertEquals(len(self.db), 0)
|
||||||
|
|
||||||
def test_db_save(self):
|
def test_db_save(self):
|
||||||
pass
|
# setup
|
||||||
|
fname = '/tmp/autojump_test_db_save_' + str(random.randint(0,32678)) + '.txt'
|
||||||
|
db = autojump.Database(fname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# test
|
||||||
|
db.save()
|
||||||
|
self.assertTrue(os.path.isfile(fname))
|
||||||
|
finally:
|
||||||
|
# teardown
|
||||||
|
os.remove(fname)
|
||||||
|
os.remove(fname + '.bak')
|
||||||
|
|
||||||
def test_db_trim(self):
|
def test_db_trim(self):
|
||||||
self.db.add('/1')
|
self.db.add('/1')
|
||||||
|
Loading…
Reference in New Issue
Block a user