Benjamin Schubert pushed to branch bschubert/set-as-set at BuildStream / buildstream
Commits:
-
39febfda
by Angelos Evripiotis at 2019-02-15T11:10:51Z
-
8b34e356
by Angelos Evripiotis at 2019-02-15T12:25:21Z
-
3bbb90e7
by Benjamin Schubert at 2019-02-15T12:34:36Z
7 changed files:
- buildstream/_loader/loader.py
- buildstream/_profile.py
- buildstream/plugins/sources/tar.py
- buildstream/storage/_casbaseddirectory.py
- buildstream/storage/_filebaseddirectory.py
- buildstream/storage/directory.py
- tests/frontend/buildcheckout.py
Changes:
| ... | ... | @@ -284,17 +284,17 @@ class Loader(): |
| 284 | 284 |
def _check_circular_deps(self, element, check_elements=None, validated=None, sequence=None):
|
| 285 | 285 |
|
| 286 | 286 |
if check_elements is None:
|
| 287 |
- check_elements = {}
|
|
| 287 |
+ check_elements = set()
|
|
| 288 | 288 |
if validated is None:
|
| 289 |
- validated = {}
|
|
| 289 |
+ validated = set()
|
|
| 290 | 290 |
if sequence is None:
|
| 291 | 291 |
sequence = []
|
| 292 | 292 |
|
| 293 | 293 |
# Skip already validated branches
|
| 294 |
- if validated.get(element) is not None:
|
|
| 294 |
+ if element in validated:
|
|
| 295 | 295 |
return
|
| 296 | 296 |
|
| 297 |
- if check_elements.get(element) is not None:
|
|
| 297 |
+ if element in check_elements:
|
|
| 298 | 298 |
# Create `chain`, the loop of element dependencies from this
|
| 299 | 299 |
# element back to itself, by trimming everything before this
|
| 300 | 300 |
# element from the sequence under consideration.
|
| ... | ... | @@ -306,15 +306,15 @@ class Loader(): |
| 306 | 306 |
.format(element.full_name, " -> ".join(chain)))
|
| 307 | 307 |
|
| 308 | 308 |
# Push / Check each dependency / Pop
|
| 309 |
- check_elements[element] = True
|
|
| 309 |
+ check_elements.add(element)
|
|
| 310 | 310 |
sequence.append(element.full_name)
|
| 311 | 311 |
for dep in element.dependencies:
|
| 312 | 312 |
dep.element._loader._check_circular_deps(dep.element, check_elements, validated, sequence)
|
| 313 |
- del check_elements[element]
|
|
| 313 |
+ check_elements.remove(element)
|
|
| 314 | 314 |
sequence.pop()
|
| 315 | 315 |
|
| 316 | 316 |
# Eliminate duplicate paths
|
| 317 |
- validated[element] = True
|
|
| 317 |
+ validated.add(element)
|
|
| 318 | 318 |
|
| 319 | 319 |
# _sort_dependencies():
|
| 320 | 320 |
#
|
| ... | ... | @@ -26,7 +26,7 @@ import datetime |
| 26 | 26 |
import time
|
| 27 | 27 |
|
| 28 | 28 |
# Track what profile topics are active
|
| 29 |
-active_topics = {}
|
|
| 29 |
+active_topics = set()
|
|
| 30 | 30 |
active_profiles = {}
|
| 31 | 31 |
initialized = False
|
| 32 | 32 |
|
| ... | ... | @@ -144,14 +144,10 @@ def profile_init(): |
| 144 | 144 |
if setting:
|
| 145 | 145 |
topics = setting.split(':')
|
| 146 | 146 |
for topic in topics:
|
| 147 |
- active_topics[topic] = True
|
|
| 147 |
+ active_topics.add(topic)
|
|
| 148 | 148 |
initialized = True
|
| 149 | 149 |
|
| 150 | 150 |
|
| 151 | 151 |
def profile_enabled(topic):
|
| 152 | 152 |
profile_init()
|
| 153 |
- if active_topics.get(topic):
|
|
| 154 |
- return True
|
|
| 155 |
- if active_topics.get(Topics.ALL):
|
|
| 156 |
- return True
|
|
| 157 |
- return False
|
|
| 153 |
+ return topic in active_topics or Topics.ALL in active_topics
|
| ... | ... | @@ -154,7 +154,7 @@ class TarSource(DownloadableFileSource): |
| 154 | 154 |
# directory paths for the archived files.
|
| 155 | 155 |
def _list_tar_paths(self, tar):
|
| 156 | 156 |
|
| 157 |
- visited = {}
|
|
| 157 |
+ visited = set()
|
|
| 158 | 158 |
for member in tar.getmembers():
|
| 159 | 159 |
|
| 160 | 160 |
# Remove any possible leading './', offer more consistent behavior
|
| ... | ... | @@ -170,7 +170,7 @@ class TarSource(DownloadableFileSource): |
| 170 | 170 |
for i in range(len(components) - 1):
|
| 171 | 171 |
dir_component = '/'.join([components[j] for j in range(i + 1)])
|
| 172 | 172 |
if dir_component not in visited:
|
| 173 |
- visited[dir_component] = True
|
|
| 173 |
+ visited.add(dir_component)
|
|
| 174 | 174 |
try:
|
| 175 | 175 |
# Dont yield directory members which actually do
|
| 176 | 176 |
# exist in the archive
|
| ... | ... | @@ -36,7 +36,7 @@ from .._protos.build.bazel.remote.execution.v2 import remote_execution_pb2 |
| 36 | 36 |
from .._exceptions import BstError
|
| 37 | 37 |
from .directory import Directory, VirtualDirectoryError
|
| 38 | 38 |
from ._filebaseddirectory import FileBasedDirectory
|
| 39 |
-from ..utils import FileListResult, safe_copy, list_relative_paths
|
|
| 39 |
+from ..utils import FileListResult, safe_copy, list_relative_paths, _magic_timestamp
|
|
| 40 | 40 |
|
| 41 | 41 |
|
| 42 | 42 |
class IndexEntry():
|
| ... | ... | @@ -535,7 +535,7 @@ class CasBasedDirectory(Directory): |
| 535 | 535 |
" The original error was: {}").
|
| 536 | 536 |
format(src_name, entry.target, e))
|
| 537 | 537 |
|
| 538 |
- def export_to_tar(self, tarfile, destination_dir, mtime=0):
|
|
| 538 |
+ def export_to_tar(self, tarfile, destination_dir, mtime=_magic_timestamp):
|
|
| 539 | 539 |
raise NotImplementedError()
|
| 540 | 540 |
|
| 541 | 541 |
def mark_changed(self):
|
| ... | ... | @@ -157,7 +157,7 @@ class FileBasedDirectory(Directory): |
| 157 | 157 |
# First, it sorts the results of os.listdir() to ensure the ordering of
|
| 158 | 158 |
# the files in the archive is the same. Second, it sets a fixed
|
| 159 | 159 |
# timestamp for each entry. See also https://bugs.python.org/issue24465.
|
| 160 |
- def export_to_tar(self, tf, dir_arcname, mtime=0):
|
|
| 160 |
+ def export_to_tar(self, tf, dir_arcname, mtime=_magic_timestamp):
|
|
| 161 | 161 |
# We need directories here, including non-empty ones,
|
| 162 | 162 |
# so list_relative_paths is not used.
|
| 163 | 163 |
for filename in sorted(os.listdir(self.external_directory)):
|
| ... | ... | @@ -32,6 +32,7 @@ See also: :ref:`sandboxing`. |
| 32 | 32 |
"""
|
| 33 | 33 |
|
| 34 | 34 |
from .._exceptions import BstError, ErrorDomain
|
| 35 |
+from ..utils import _magic_timestamp
|
|
| 35 | 36 |
|
| 36 | 37 |
|
| 37 | 38 |
class VirtualDirectoryError(BstError):
|
| ... | ... | @@ -114,7 +115,7 @@ class Directory(): |
| 114 | 115 |
|
| 115 | 116 |
raise NotImplementedError()
|
| 116 | 117 |
|
| 117 |
- def export_to_tar(self, tarfile, destination_dir, mtime=0):
|
|
| 118 |
+ def export_to_tar(self, tarfile, destination_dir, mtime=_magic_timestamp):
|
|
| 118 | 119 |
""" Exports this directory into the given tar file.
|
| 119 | 120 |
|
| 120 | 121 |
Args:
|
| ... | ... | @@ -252,6 +252,26 @@ def test_build_checkout_tarball_stdout(datafiles, cli): |
| 252 | 252 |
assert os.path.join('.', 'usr', 'include', 'pony.h') in tar.getnames()
|
| 253 | 253 |
|
| 254 | 254 |
|
| 255 |
+@pytest.mark.datafiles(DATA_DIR)
|
|
| 256 |
+def test_build_checkout_tarball_mtime_nonzero(datafiles, cli):
|
|
| 257 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
| 258 |
+ tarpath = os.path.join(cli.directory, 'mtime_tar.tar')
|
|
| 259 |
+ |
|
| 260 |
+ result = cli.run(project=project, args=['build', 'target.bst'])
|
|
| 261 |
+ result.assert_success()
|
|
| 262 |
+ |
|
| 263 |
+ checkout_args = ['artifact', 'checkout', '--tar', tarpath, 'target.bst']
|
|
| 264 |
+ result = cli.run(project=project, args=checkout_args)
|
|
| 265 |
+ result.assert_success()
|
|
| 266 |
+ |
|
| 267 |
+ tar = tarfile.TarFile(tarpath)
|
|
| 268 |
+ for tarinfo in tar.getmembers():
|
|
| 269 |
+ # An mtime of zero can be confusing to other software,
|
|
| 270 |
+ # e.g. ninja build and template toolkit have both taken zero mtime to
|
|
| 271 |
+ # mean 'file does not exist'.
|
|
| 272 |
+ assert tarinfo.mtime > 0
|
|
| 273 |
+ |
|
| 274 |
+ |
|
| 255 | 275 |
@pytest.mark.datafiles(DATA_DIR)
|
| 256 | 276 |
def test_build_checkout_tarball_is_deterministic(datafiles, cli):
|
| 257 | 277 |
project = os.path.join(datafiles.dirname, datafiles.basename)
|
