Skip to content

Commit 96edb82

Browse files
Lotramryneeverett
authored andcommitted
Move to filelock library
lockfile has been deprecated for a long-time while filelock is well-maintained timeout message has changed because the existence of the lock file does not mean the file is actually locked anymore. Locks are handled by the OS Refs: #1183
1 parent 3844120 commit 96edb82

4 files changed

Lines changed: 28 additions & 13 deletions

File tree

bugwarrior/command.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
import warnings
99

1010
import click
11-
from lockfile import LockTimeout
12-
from lockfile.pidlockfile import PIDLockFile
11+
from filelock import FileLock, Timeout
1312

1413
from bugwarrior.collect import aggregate_issues
1514
from bugwarrior.config import get_config_path, get_keyring, load_config
@@ -123,21 +122,17 @@ def pull(
123122
config = _try_load_config(main_section, quiet)
124123

125124
lockfile_path = os.path.join(config.main.data.path, 'bugwarrior.lockfile')
126-
lockfile = PIDLockFile(lockfile_path)
127-
lockfile.acquire(timeout=10)
128-
try:
125+
with FileLock(lockfile_path, timeout=10):
129126
# Get all the issues. This can take a while.
130127
issue_generator = aggregate_issues(config, debug)
131128

132129
# Stuff them in the taskwarrior db as necessary
133130
synchronize(issue_generator, config, dry_run)
134-
finally:
135-
lockfile.release()
136-
except LockTimeout:
131+
except Timeout:
137132
log.critical(
138133
'Your taskrc repository is currently locked. '
139-
'Remove the file at %s if you are sure no other '
140-
'bugwarrior processes are currently running.' % (lockfile_path)
134+
'Wait for any running bugwarrior processes to finish and try again. '
135+
f'Lock file:{lockfile_path}'
141136
)
142137
sys.exit(1)
143138
except RuntimeError as e:

bugwarrior/config/data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import subprocess
55
import typing
66

7-
from lockfile.pidlockfile import PIDLockFile
7+
from filelock import FileLock
88

99

1010
def get_data_path(taskrc: str | Path) -> str:
@@ -65,7 +65,7 @@ def get(self, key: str) -> typing.Any:
6565

6666
def set(self, key: str, value: typing.Any) -> None:
6767
"""Set a value in the ``bugwarrior.data`` file."""
68-
with PIDLockFile(self._lockfile):
68+
with FileLock(self._lockfile):
6969
try:
7070
data = self.get_data()
7171
except OSError: # File does not exist.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dependencies = [
1818
"click",
1919
"dogpile.cache>=0.5.3",
2020
"jinja2>=2.7.2",
21-
"lockfile>=0.9.1",
21+
"filelock>=3",
2222
"pydantic[email]>=2",
2323
"python-dateutil",
2424
"requests>=1",

tests/test_command.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,26 @@ def test_partial_failure_database_integrity(self, bugzillalib):
173173
self.assertNotIn('Closing 1 tasks', logs)
174174
self.assertNotIn('Completing task', logs)
175175

176+
@mock.patch('bugwarrior.command.FileLock')
177+
def test_locked_repository(self, file_lock):
178+
"""
179+
A locked task repository should abort the pull.
180+
"""
181+
lockfile_path = pathlib.Path(self.lists_path) / 'bugwarrior.lockfile'
182+
file_lock.return_value.__enter__.side_effect = command.Timeout(
183+
str(lockfile_path)
184+
)
185+
186+
with self.caplog.at_level(logging.CRITICAL):
187+
result = self.runner.invoke(command.cli, args=('pull', '--debug'))
188+
189+
self.assertEqual(result.exit_code, 1)
190+
file_lock.assert_called_once_with(str(lockfile_path), timeout=10)
191+
logs = [rec.message for rec in self.caplog.records]
192+
self.assertTrue(
193+
any('Your taskrc repository is currently locked.' in log for log in logs)
194+
)
195+
176196
@mock.patch('bugwarrior.services.github.GithubService.issues', fake_github_issues)
177197
def test_legacy_cli(self):
178198
"""

0 commit comments

Comments
 (0)