summaryrefslogtreecommitdiff
path: root/buildstream/plugins/sources/local.py
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:54:36 +0000
commitccf6e479df23c2f28ea56f237459d32086af1406 (patch)
treea95c10de452a25d7bfe7d3517600f744fed999a3 /buildstream/plugins/sources/local.py
parent48c715e3f5eb06372f75dcf778f0278273569812 (diff)
downloadbuildstream-ccf6e479df23c2f28ea56f237459d32086af1406.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.
Diffstat (limited to 'buildstream/plugins/sources/local.py')
-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):