summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin David <valentin.david@codethink.co.uk>2018-08-06 17:13:21 +0200
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2018-08-12 05:57:44 +0000
commitb9f6b1d7f538c2c6e4b2f075c20d8f4a583e9120 (patch)
tree3b415daa51c88a440579a6ffafeba8bf4db4d01a
parent37742ac7a2b1b6aaaa460da0be30495c3c1a60db (diff)
downloadbuildstream-b9f6b1d7f538c2c6e4b2f075c20d8f4a583e9120.tar.gz
buildstream/plugins/sources/local.py: Make staging deterministic.
Instead of copying metadata on files staged by local, we manually set mode to 0755 or 0644 depending on whether user execution was enabled on source file. This makes file modes deterministic independently on the way source was distributed. Non-deterministic mode copying all metadata can still be enabled by disable 'deterministic' Boolean configuration on the plugin. Fixes #527.
-rw-r--r--buildstream/plugins/sources/local.py26
1 files changed, 25 insertions, 1 deletions
diff --git a/buildstream/plugins/sources/local.py b/buildstream/plugins/sources/local.py
index 058553424..7c19e1f90 100644
--- a/buildstream/plugins/sources/local.py
+++ b/buildstream/plugins/sources/local.py
@@ -37,6 +37,7 @@ local - stage local files and directories
"""
import os
+import stat
from buildstream import Source, Consistency
from buildstream import utils
@@ -94,12 +95,35 @@ class LocalSource(Source):
# Dont use hardlinks to stage sources, they are not write protected
# in the sandbox.
with self.timed_activity("Staging local files at {}".format(self.path)):
+
if os.path.isdir(self.fullpath):
- utils.copy_files(self.fullpath, directory)
+ files = list(utils.list_relative_paths(self.fullpath, list_dirs=True))
+ utils.copy_files(self.fullpath, directory, files=files)
else:
destfile = os.path.join(directory, os.path.basename(self.path))
+ files = [os.path.basename(self.path)]
utils.safe_copy(self.fullpath, destfile)
+ for f in files:
+ # Non empty directories are not listed by list_relative_paths
+ dirs = f.split(os.sep)
+ for i in range(1, len(dirs)):
+ d = os.path.join(directory, *(dirs[:i]))
+ assert os.path.isdir(d) and not os.path.islink(d)
+ os.chmod(d, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
+
+ path = os.path.join(directory, f)
+ if os.path.islink(path):
+ pass
+ elif os.path.isdir(path):
+ os.chmod(path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
+ else:
+ st = os.stat(path)
+ if st.st_mode & stat.S_IXUSR:
+ os.chmod(path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
+ else:
+ os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
+
# Create a unique key for a file
def unique_key(filename):