summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2019-01-17 14:46:18 -0500
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2019-04-14 15:38:50 +0900
commitd3b559e050837a14ce8f9c36c358940d1b197242 (patch)
treeb3ffa330c1f5b7e53c2e07db39b079d911a7777d
parent5dce02bbd68be31b67b080ac6480af359f826609 (diff)
downloadbuildstream-d3b559e050837a14ce8f9c36c358940d1b197242.tar.gz
bzr source plugin: Use lock files to avoid corrupting the source cache
This patch by itself fixes #868
-rw-r--r--buildstream/plugins/sources/bzr.py35
1 files changed, 29 insertions, 6 deletions
diff --git a/buildstream/plugins/sources/bzr.py b/buildstream/plugins/sources/bzr.py
index c1e289704..3cb62176d 100644
--- a/buildstream/plugins/sources/bzr.py
+++ b/buildstream/plugins/sources/bzr.py
@@ -57,6 +57,7 @@ bzr - stage files from a bazaar repository
import os
import shutil
+import fcntl
from contextlib import contextmanager
from buildstream import Source, SourceError, Consistency
@@ -85,10 +86,12 @@ class BzrSource(Source):
if self.ref is None or self.tracking is None:
return Consistency.INCONSISTENT
- if self._check_ref():
- return Consistency.CACHED
- else:
- return Consistency.RESOLVED
+ # Lock for the _check_ref()
+ with self._locked():
+ if self._check_ref():
+ return Consistency.CACHED
+ else:
+ return Consistency.RESOLVED
def load_ref(self, node):
self.ref = self.node_get_member(node, str, 'ref', None)
@@ -101,7 +104,7 @@ class BzrSource(Source):
def track(self):
with self.timed_activity("Tracking {}".format(self.url),
- silent_nested=True):
+ silent_nested=True), self._locked():
self._ensure_mirror(skip_ref_check=True)
ret, out = self.check_output([self.host_bzr, "version-info",
"--custom", "--template={revno}",
@@ -115,7 +118,7 @@ class BzrSource(Source):
def fetch(self):
with self.timed_activity("Fetching {}".format(self.url),
- silent_nested=True):
+ silent_nested=True), self._locked():
self._ensure_mirror()
def stage(self, directory):
@@ -140,6 +143,26 @@ class BzrSource(Source):
"--directory={}".format(directory), url],
fail="Failed to switch workspace's parent branch to {}".format(url))
+ # _locked()
+ #
+ # This context manager ensures exclusive access to the
+ # bzr repository.
+ #
+ @contextmanager
+ def _locked(self):
+ lockdir = os.path.join(self.get_mirror_directory(), 'locks')
+ lockfile = os.path.join(
+ lockdir,
+ utils.url_directory_name(self.original_url) + '.lock'
+ )
+ os.makedirs(lockdir, exist_ok=True)
+ with open(lockfile, 'w') as lock:
+ fcntl.flock(lock, fcntl.LOCK_EX)
+ try:
+ yield
+ finally:
+ fcntl.flock(lock, fcntl.LOCK_UN)
+
def _check_ref(self):
# If the mirror doesnt exist yet, then we dont have the ref
if not os.path.exists(self._get_branch_dir()):