Jim MacArthur pushed to branch jmac/virtual_directories at BuildStream / buildstream
Commits:
-
785642b6
by Jim MacArthur at 2018-08-01T11:36:47Z
-
ed7c610d
by Jim MacArthur at 2018-08-01T11:36:47Z
-
b030d0a4
by Jim MacArthur at 2018-08-01T11:36:47Z
-
6bdfe94a
by Jim MacArthur at 2018-08-01T11:36:47Z
-
87a77e9f
by Jim MacArthur at 2018-08-01T11:36:47Z
-
206f6bb4
by Jim MacArthur at 2018-08-01T11:36:47Z
-
1de89f92
by Jim MacArthur at 2018-08-01T11:36:47Z
-
b0ff6db1
by Jim MacArthur at 2018-08-01T11:36:47Z
8 changed files:
- buildstream/element.py
- buildstream/plugins/elements/compose.py
- buildstream/plugins/elements/import.py
- buildstream/plugins/elements/stack.py
- buildstream/sandbox/_mount.py
- buildstream/sandbox/_sandboxbwrap.py
- buildstream/sandbox/sandbox.py
- buildstream/scriptelement.py
Changes:
... | ... | @@ -80,7 +80,6 @@ from collections import Mapping, OrderedDict |
80 | 80 |
from contextlib import contextmanager
|
81 | 81 |
from enum import Enum
|
82 | 82 |
import tempfile
|
83 |
-import time
|
|
84 | 83 |
import shutil
|
85 | 84 |
|
86 | 85 |
from . import _yaml
|
... | ... | @@ -97,6 +96,10 @@ from . import _site |
97 | 96 |
from ._platform import Platform
|
98 | 97 |
from .sandbox._config import SandboxConfig
|
99 | 98 |
|
99 |
+from .storage.directory import Directory
|
|
100 |
+from .storage._filebaseddirectory import FileBasedDirectory, VirtualDirectoryError
|
|
101 |
+ |
|
102 |
+ |
|
100 | 103 |
# _KeyStrength():
|
101 | 104 |
#
|
102 | 105 |
# Strength of cache key
|
... | ... | @@ -198,7 +201,7 @@ class Element(Plugin): |
198 | 201 |
"""Whether to raise exceptions if an element uses Sandbox.get_directory
|
199 | 202 |
instead of Sandbox.get_virtual_directory.
|
200 | 203 |
|
201 |
- *Since: 1.2*
|
|
204 |
+ *Since: 1.4*
|
|
202 | 205 |
"""
|
203 | 206 |
|
204 | 207 |
def __init__(self, context, project, artifacts, meta, plugin_conf):
|
... | ... | @@ -633,10 +636,10 @@ class Element(Plugin): |
633 | 636 |
|
634 | 637 |
# Hard link it into the staging area
|
635 | 638 |
#
|
636 |
- basedir = sandbox.get_directory()
|
|
637 |
- stagedir = basedir \
|
|
639 |
+ vbasedir = sandbox.get_virtual_directory()
|
|
640 |
+ vstagedir = vbasedir \
|
|
638 | 641 |
if path is None \
|
639 |
- else os.path.join(basedir, path.lstrip(os.sep))
|
|
642 |
+ else vbasedir.descend(path.lstrip(os.sep).split(os.sep))
|
|
640 | 643 |
|
641 | 644 |
files = list(self.__compute_splits(include, exclude, orphans))
|
642 | 645 |
|
... | ... | @@ -648,15 +651,8 @@ class Element(Plugin): |
648 | 651 |
link_files = files
|
649 | 652 |
copy_files = []
|
650 | 653 |
|
651 |
- link_result = utils.link_files(artifact, stagedir, files=link_files,
|
|
652 |
- report_written=True)
|
|
653 |
- copy_result = utils.copy_files(artifact, stagedir, files=copy_files,
|
|
654 |
- report_written=True)
|
|
655 |
- |
|
656 |
- cur_time = time.time()
|
|
657 |
- |
|
658 |
- for f in copy_result.files_written:
|
|
659 |
- os.utime(os.path.join(stagedir, f), times=(cur_time, cur_time))
|
|
654 |
+ link_result = vstagedir.import_files(artifact, files=link_files, report_written=True, can_link=True)
|
|
655 |
+ copy_result = vstagedir.import_files(artifact, files=copy_files, report_written=True, update_utimes=True)
|
|
660 | 656 |
|
661 | 657 |
return link_result.combine(copy_result)
|
662 | 658 |
|
... | ... | @@ -1365,40 +1361,45 @@ class Element(Plugin): |
1365 | 1361 |
sandbox._set_mount_source(directory, workspace.get_absolute_path())
|
1366 | 1362 |
|
1367 | 1363 |
# Stage all sources that need to be copied
|
1368 |
- sandbox_root = sandbox.get_directory()
|
|
1369 |
- host_directory = os.path.join(sandbox_root, directory.lstrip(os.sep))
|
|
1370 |
- self._stage_sources_at(host_directory, mount_workspaces=mount_workspaces)
|
|
1364 |
+ sandbox_vroot = sandbox.get_virtual_directory()
|
|
1365 |
+ host_vdirectory = sandbox_vroot.descend(directory.lstrip(os.sep).split(os.sep), create=True)
|
|
1366 |
+ self._stage_sources_at(host_vdirectory, mount_workspaces=mount_workspaces)
|
|
1371 | 1367 |
|
1372 | 1368 |
# _stage_sources_at():
|
1373 | 1369 |
#
|
1374 | 1370 |
# Stage this element's sources to a directory
|
1375 | 1371 |
#
|
1376 | 1372 |
# Args:
|
1377 |
- # directory (str): An absolute path to stage the sources at
|
|
1373 |
+ # vdirectory (:class:`.storage.Directory`): A virtual directory object to stage sources into.
|
|
1378 | 1374 |
# mount_workspaces (bool): mount workspaces if True, copy otherwise
|
1379 | 1375 |
#
|
1380 |
- def _stage_sources_at(self, directory, mount_workspaces=True):
|
|
1376 |
+ def _stage_sources_at(self, vdirectory, mount_workspaces=True):
|
|
1381 | 1377 |
with self.timed_activity("Staging sources", silent_nested=True):
|
1382 | 1378 |
|
1383 |
- if os.path.isdir(directory) and os.listdir(directory):
|
|
1384 |
- raise ElementError("Staging directory '{}' is not empty".format(directory))
|
|
1385 |
- |
|
1386 |
- workspace = self._get_workspace()
|
|
1387 |
- if workspace:
|
|
1388 |
- # If mount_workspaces is set and we're doing incremental builds,
|
|
1389 |
- # the workspace is already mounted into the sandbox.
|
|
1390 |
- if not (mount_workspaces and self.__can_build_incrementally()):
|
|
1391 |
- with self.timed_activity("Staging local files at {}".format(workspace.path)):
|
|
1392 |
- workspace.stage(directory)
|
|
1393 |
- else:
|
|
1394 |
- # No workspace, stage directly
|
|
1395 |
- for source in self.sources():
|
|
1396 |
- source._stage(directory)
|
|
1397 |
- |
|
1379 |
+ if not isinstance(vdirectory, Directory):
|
|
1380 |
+ vdirectory = FileBasedDirectory(vdirectory)
|
|
1381 |
+ if not vdirectory.is_empty():
|
|
1382 |
+ raise ElementError("Staging directory '{}' is not empty".format(vdirectory))
|
|
1383 |
+ |
|
1384 |
+ with tempfile.TemporaryDirectory() as temp_staging_directory:
|
|
1385 |
+ |
|
1386 |
+ workspace = self._get_workspace()
|
|
1387 |
+ if workspace:
|
|
1388 |
+ # If mount_workspaces is set and we're doing incremental builds,
|
|
1389 |
+ # the workspace is already mounted into the sandbox.
|
|
1390 |
+ if not (mount_workspaces and self.__can_build_incrementally()):
|
|
1391 |
+ with self.timed_activity("Staging local files at {}".format(workspace.path)):
|
|
1392 |
+ workspace.stage(temp_staging_directory)
|
|
1393 |
+ else:
|
|
1394 |
+ # No workspace, stage directly
|
|
1395 |
+ for source in self.sources():
|
|
1396 |
+ source._stage(temp_staging_directory)
|
|
1397 |
+ |
|
1398 |
+ vdirectory.import_files(temp_staging_directory)
|
|
1398 | 1399 |
# Ensure deterministic mtime of sources at build time
|
1399 |
- utils._set_deterministic_mtime(directory)
|
|
1400 |
+ vdirectory.set_deterministic_mtime()
|
|
1400 | 1401 |
# Ensure deterministic owners of sources at build time
|
1401 |
- utils._set_deterministic_user(directory)
|
|
1402 |
+ vdirectory.set_deterministic_user()
|
|
1402 | 1403 |
|
1403 | 1404 |
# _set_required():
|
1404 | 1405 |
#
|
... | ... | @@ -1514,7 +1515,7 @@ class Element(Plugin): |
1514 | 1515 |
with _signals.terminator(cleanup_rootdir), \
|
1515 | 1516 |
self.__sandbox(rootdir, output_file, output_file, self.__sandbox_config) as sandbox: # nopep8
|
1516 | 1517 |
|
1517 |
- sandbox_root = sandbox.get_directory()
|
|
1518 |
+ sandbox_vroot = sandbox.get_virtual_directory()
|
|
1518 | 1519 |
|
1519 | 1520 |
# By default, the dynamic public data is the same as the static public data.
|
1520 | 1521 |
# The plugin's assemble() method may modify this, though.
|
... | ... | @@ -1546,11 +1547,11 @@ class Element(Plugin): |
1546 | 1547 |
#
|
1547 | 1548 |
workspace = self._get_workspace()
|
1548 | 1549 |
if workspace and self.__staged_sources_directory:
|
1549 |
- sandbox_root = sandbox.get_directory()
|
|
1550 |
- sandbox_path = os.path.join(sandbox_root,
|
|
1551 |
- self.__staged_sources_directory.lstrip(os.sep))
|
|
1550 |
+ sandbox_vroot = sandbox.get_virtual_directory()
|
|
1551 |
+ path_components = self.__staged_sources_directory.lstrip(os.sep).split(os.sep)
|
|
1552 |
+ sandbox_vpath = sandbox_vroot.descend(path_components)
|
|
1552 | 1553 |
try:
|
1553 |
- utils.copy_files(workspace.path, sandbox_path)
|
|
1554 |
+ sandbox_vpath.import_files(workspace.path)
|
|
1554 | 1555 |
except UtilError as e:
|
1555 | 1556 |
self.warn("Failed to preserve workspace state for failed build sysroot: {}"
|
1556 | 1557 |
.format(e))
|
... | ... | @@ -1562,7 +1563,11 @@ class Element(Plugin): |
1562 | 1563 |
raise
|
1563 | 1564 |
finally:
|
1564 | 1565 |
if collect is not None:
|
1565 |
- collectdir = os.path.join(sandbox_root, collect.lstrip(os.sep))
|
|
1566 |
+ try:
|
|
1567 |
+ collectvdir = sandbox_vroot.descend(collect.lstrip(os.sep).split(os.sep))
|
|
1568 |
+ except VirtualDirectoryError:
|
|
1569 |
+ # No collect directory existed
|
|
1570 |
+ collectvdir = None
|
|
1566 | 1571 |
|
1567 | 1572 |
# Create artifact directory structure
|
1568 | 1573 |
assembledir = os.path.join(rootdir, 'artifact')
|
... | ... | @@ -1571,20 +1576,26 @@ class Element(Plugin): |
1571 | 1576 |
metadir = os.path.join(assembledir, 'meta')
|
1572 | 1577 |
buildtreedir = os.path.join(assembledir, 'buildtree')
|
1573 | 1578 |
os.mkdir(assembledir)
|
1574 |
- if collect is not None and os.path.exists(collectdir):
|
|
1579 |
+ if collect is not None and collectvdir is not None:
|
|
1575 | 1580 |
os.mkdir(filesdir)
|
1576 | 1581 |
os.mkdir(logsdir)
|
1577 | 1582 |
os.mkdir(metadir)
|
1578 | 1583 |
os.mkdir(buildtreedir)
|
1579 | 1584 |
|
1580 | 1585 |
# Hard link files from collect dir to files directory
|
1581 |
- if collect is not None and os.path.exists(collectdir):
|
|
1582 |
- utils.link_files(collectdir, filesdir)
|
|
1583 |
- |
|
1584 |
- sandbox_build_dir = os.path.join(sandbox_root, self.get_variable('build-root').lstrip(os.sep))
|
|
1585 |
- # Hard link files from build-root dir to buildtreedir directory
|
|
1586 |
- if os.path.isdir(sandbox_build_dir):
|
|
1587 |
- utils.link_files(sandbox_build_dir, buildtreedir)
|
|
1586 |
+ if collect is not None and collectvdir is not None:
|
|
1587 |
+ collectvdir.export_files(filesdir, can_link=True)
|
|
1588 |
+ |
|
1589 |
+ try:
|
|
1590 |
+ sandbox_build_dir = sandbox_vroot.descend(
|
|
1591 |
+ self.get_variable('build-root').lstrip(os.sep).split(os.sep))
|
|
1592 |
+ # Hard link files from build-root dir to buildtreedir directory
|
|
1593 |
+ sandbox_build_dir.export_files(buildtreedir)
|
|
1594 |
+ except VirtualDirectoryError:
|
|
1595 |
+ # Directory could not be found. Pre-virtual
|
|
1596 |
+ # directory behaviour was to continue silently
|
|
1597 |
+ # if the directory could not be found.
|
|
1598 |
+ pass
|
|
1588 | 1599 |
|
1589 | 1600 |
# Copy build log
|
1590 | 1601 |
log_filename = context.get_log_filename()
|
... | ... | @@ -1632,7 +1643,7 @@ class Element(Plugin): |
1632 | 1643 |
self.__artifact_size = utils._get_dir_size(assembledir)
|
1633 | 1644 |
self.__artifacts.commit(self, assembledir, self.__get_cache_keys_for_commit())
|
1634 | 1645 |
|
1635 |
- if collect is not None and not os.path.exists(collectdir):
|
|
1646 |
+ if collect is not None and collectvdir is None:
|
|
1636 | 1647 |
raise ElementError(
|
1637 | 1648 |
"Directory '{}' was not found inside the sandbox, "
|
1638 | 1649 |
"unable to collect artifact contents"
|
... | ... | @@ -34,7 +34,6 @@ The default configuration and possible options are as such: |
34 | 34 |
"""
|
35 | 35 |
|
36 | 36 |
import os
|
37 |
-from buildstream import utils
|
|
38 | 37 |
from buildstream import Element, Scope
|
39 | 38 |
|
40 | 39 |
|
... | ... | @@ -56,6 +55,9 @@ class ComposeElement(Element): |
56 | 55 |
# added, to reduce the potential for confusion
|
57 | 56 |
BST_FORBID_SOURCES = True
|
58 | 57 |
|
58 |
+ # This plugin has been modified to avoid the use of Sandbox.get_directory
|
|
59 |
+ BST_VIRTUAL_DIRECTORY = True
|
|
60 |
+ |
|
59 | 61 |
def configure(self, node):
|
60 | 62 |
self.node_validate(node, [
|
61 | 63 |
'integrate', 'include', 'exclude', 'include-orphans'
|
... | ... | @@ -104,7 +106,8 @@ class ComposeElement(Element): |
104 | 106 |
orphans=self.include_orphans)
|
105 | 107 |
manifest.update(files)
|
106 | 108 |
|
107 |
- basedir = sandbox.get_directory()
|
|
109 |
+ # Make a snapshot of all the files.
|
|
110 |
+ vbasedir = sandbox.get_virtual_directory()
|
|
108 | 111 |
modified_files = set()
|
109 | 112 |
removed_files = set()
|
110 | 113 |
added_files = set()
|
... | ... | @@ -116,38 +119,24 @@ class ComposeElement(Element): |
116 | 119 |
if require_split:
|
117 | 120 |
|
118 | 121 |
# Make a snapshot of all the files before integration-commands are run.
|
119 |
- snapshot = {
|
|
120 |
- f: getmtime(os.path.join(basedir, f))
|
|
121 |
- for f in utils.list_relative_paths(basedir)
|
|
122 |
- }
|
|
122 |
+ snapshot = set(vbasedir.list_relative_paths())
|
|
123 |
+ vbasedir.mark_unmodified()
|
|
123 | 124 |
|
124 | 125 |
for dep in self.dependencies(Scope.BUILD):
|
125 | 126 |
dep.integrate(sandbox)
|
126 | 127 |
|
127 | 128 |
if require_split:
|
128 |
- |
|
129 | 129 |
# Calculate added, modified and removed files
|
130 |
- basedir_contents = set(utils.list_relative_paths(basedir))
|
|
130 |
+ post_integration_snapshot = vbasedir.list_relative_paths()
|
|
131 |
+ modified_files = set(vbasedir.list_modified_paths())
|
|
132 |
+ basedir_contents = set(post_integration_snapshot)
|
|
131 | 133 |
for path in manifest:
|
132 |
- if path in basedir_contents:
|
|
133 |
- if path in snapshot:
|
|
134 |
- preintegration_mtime = snapshot[path]
|
|
135 |
- if preintegration_mtime != getmtime(os.path.join(basedir, path)):
|
|
136 |
- modified_files.add(path)
|
|
137 |
- else:
|
|
138 |
- # If the path appears in the manifest but not the initial snapshot,
|
|
139 |
- # it may be a file staged inside a directory symlink. In this case
|
|
140 |
- # the path we got from the manifest won't show up in the snapshot
|
|
141 |
- # because utils.list_relative_paths() doesn't recurse into symlink
|
|
142 |
- # directories.
|
|
143 |
- pass
|
|
144 |
- elif path in snapshot:
|
|
134 |
+ if path in snapshot and path not in basedir_contents:
|
|
145 | 135 |
removed_files.add(path)
|
146 | 136 |
|
147 | 137 |
for path in basedir_contents:
|
148 | 138 |
if path not in snapshot:
|
149 | 139 |
added_files.add(path)
|
150 |
- |
|
151 | 140 |
self.info("Integration modified {}, added {} and removed {} files"
|
152 | 141 |
.format(len(modified_files), len(added_files), len(removed_files)))
|
153 | 142 |
|
... | ... | @@ -166,8 +155,7 @@ class ComposeElement(Element): |
166 | 155 |
# instead of into a subdir. The element assemble() method should
|
167 | 156 |
# support this in some way.
|
168 | 157 |
#
|
169 |
- installdir = os.path.join(basedir, 'buildstream', 'install')
|
|
170 |
- os.makedirs(installdir, exist_ok=True)
|
|
158 |
+ installdir = vbasedir.descend(['buildstream', 'install'], create=True)
|
|
171 | 159 |
|
172 | 160 |
# We already saved the manifest for created files in the integration phase,
|
173 | 161 |
# now collect the rest of the manifest.
|
... | ... | @@ -191,19 +179,12 @@ class ComposeElement(Element): |
191 | 179 |
|
192 | 180 |
with self.timed_activity("Creating composition", detail=detail, silent_nested=True):
|
193 | 181 |
self.info("Composing {} files".format(len(manifest)))
|
194 |
- utils.link_files(basedir, installdir, files=manifest)
|
|
182 |
+ installdir.import_files(vbasedir, files=manifest, can_link=True)
|
|
195 | 183 |
|
196 | 184 |
# And we're done
|
197 | 185 |
return os.path.join(os.sep, 'buildstream', 'install')
|
198 | 186 |
|
199 | 187 |
|
200 |
-# Like os.path.getmtime(), but doesnt explode on symlinks
|
|
201 |
-#
|
|
202 |
-def getmtime(path):
|
|
203 |
- stat = os.lstat(path)
|
|
204 |
- return stat.st_mtime
|
|
205 |
- |
|
206 |
- |
|
207 | 188 |
# Plugin entry point
|
208 | 189 |
def setup():
|
209 | 190 |
return ComposeElement
|
... | ... | @@ -31,7 +31,6 @@ The empty configuration is as such: |
31 | 31 |
"""
|
32 | 32 |
|
33 | 33 |
import os
|
34 |
-import shutil
|
|
35 | 34 |
from buildstream import Element, BuildElement, ElementError
|
36 | 35 |
|
37 | 36 |
|
... | ... | @@ -39,6 +38,9 @@ from buildstream import Element, BuildElement, ElementError |
39 | 38 |
class ImportElement(BuildElement):
|
40 | 39 |
# pylint: disable=attribute-defined-outside-init
|
41 | 40 |
|
41 |
+ # This plugin has been modified to avoid the use of Sandbox.get_directory
|
|
42 |
+ BST_VIRTUAL_DIRECTORY = True
|
|
43 |
+ |
|
42 | 44 |
def configure(self, node):
|
43 | 45 |
self.source = self.node_subst_member(node, 'source')
|
44 | 46 |
self.target = self.node_subst_member(node, 'target')
|
... | ... | @@ -68,27 +70,22 @@ class ImportElement(BuildElement): |
68 | 70 |
# Do not mount workspaces as the files are copied from outside the sandbox
|
69 | 71 |
self._stage_sources_in_sandbox(sandbox, 'input', mount_workspaces=False)
|
70 | 72 |
|
71 |
- rootdir = sandbox.get_directory()
|
|
72 |
- inputdir = os.path.join(rootdir, 'input')
|
|
73 |
- outputdir = os.path.join(rootdir, 'output')
|
|
73 |
+ rootdir = sandbox.get_virtual_directory()
|
|
74 |
+ inputdir = rootdir.descend(['input'])
|
|
75 |
+ outputdir = rootdir.descend(['output'], create=True)
|
|
74 | 76 |
|
75 | 77 |
# The directory to grab
|
76 |
- inputdir = os.path.join(inputdir, self.source.lstrip(os.sep))
|
|
77 |
- inputdir = inputdir.rstrip(os.sep)
|
|
78 |
+ inputdir = inputdir.descend(self.source.strip(os.sep).split(os.sep))
|
|
78 | 79 |
|
79 | 80 |
# The output target directory
|
80 |
- outputdir = os.path.join(outputdir, self.target.lstrip(os.sep))
|
|
81 |
- outputdir = outputdir.rstrip(os.sep)
|
|
82 |
- |
|
83 |
- # Ensure target directory parent
|
|
84 |
- os.makedirs(os.path.dirname(outputdir), exist_ok=True)
|
|
81 |
+ outputdir = outputdir.descend(self.target.strip(os.sep).split(os.sep), create=True)
|
|
85 | 82 |
|
86 |
- if not os.path.exists(inputdir):
|
|
83 |
+ if inputdir.is_empty():
|
|
87 | 84 |
raise ElementError("{}: No files were found inside directory '{}'"
|
88 | 85 |
.format(self, self.source))
|
89 | 86 |
|
90 | 87 |
# Move it over
|
91 |
- shutil.move(inputdir, outputdir)
|
|
88 |
+ outputdir.import_files(inputdir)
|
|
92 | 89 |
|
93 | 90 |
# And we're done
|
94 | 91 |
return '/output'
|
... | ... | @@ -24,13 +24,15 @@ Stack elements are simply a symbolic element used for representing |
24 | 24 |
a logical group of elements.
|
25 | 25 |
"""
|
26 | 26 |
|
27 |
-import os
|
|
28 | 27 |
from buildstream import Element
|
29 | 28 |
|
30 | 29 |
|
31 | 30 |
# Element implementation for the 'stack' kind.
|
32 | 31 |
class StackElement(Element):
|
33 | 32 |
|
33 |
+ # This plugin has been modified to avoid the use of Sandbox.get_directory
|
|
34 |
+ BST_VIRTUAL_DIRECTORY = True
|
|
35 |
+ |
|
34 | 36 |
def configure(self, node):
|
35 | 37 |
pass
|
36 | 38 |
|
... | ... | @@ -52,7 +54,7 @@ class StackElement(Element): |
52 | 54 |
|
53 | 55 |
# Just create a dummy empty artifact, its existence is a statement
|
54 | 56 |
# that all this stack's dependencies are built.
|
55 |
- rootdir = sandbox.get_directory()
|
|
57 |
+ vrootdir = sandbox.get_virtual_directory()
|
|
56 | 58 |
|
57 | 59 |
# XXX FIXME: This is currently needed because the artifact
|
58 | 60 |
# cache wont let us commit an empty artifact.
|
... | ... | @@ -61,10 +63,7 @@ class StackElement(Element): |
61 | 63 |
# the actual artifact data in a subdirectory, then we
|
62 | 64 |
# will be able to store some additional state in the
|
63 | 65 |
# artifact cache, and we can also remove this hack.
|
64 |
- outputdir = os.path.join(rootdir, 'output', 'bst')
|
|
65 |
- |
|
66 |
- # Ensure target directory parent
|
|
67 |
- os.makedirs(os.path.dirname(outputdir), exist_ok=True)
|
|
66 |
+ vrootdir.descend(['output', 'bst'], create=True)
|
|
68 | 67 |
|
69 | 68 |
# And we're done
|
70 | 69 |
return '/output'
|
... | ... | @@ -32,7 +32,8 @@ from .._fuse import SafeHardlinks |
32 | 32 |
class Mount():
|
33 | 33 |
def __init__(self, sandbox, mount_point, safe_hardlinks):
|
34 | 34 |
scratch_directory = sandbox._get_scratch_directory()
|
35 |
- root_directory = sandbox.get_directory()
|
|
35 |
+ # Getting external_directory here is acceptable as we're part of the sandbox code.
|
|
36 |
+ root_directory = sandbox.get_virtual_directory().external_directory
|
|
36 | 37 |
|
37 | 38 |
self.mount_point = mount_point
|
38 | 39 |
self.safe_hardlinks = safe_hardlinks
|
... | ... | @@ -56,7 +56,9 @@ class SandboxBwrap(Sandbox): |
56 | 56 |
|
57 | 57 |
def run(self, command, flags, *, cwd=None, env=None):
|
58 | 58 |
stdout, stderr = self._get_output()
|
59 |
- root_directory = self.get_directory()
|
|
59 |
+ |
|
60 |
+ # Allowable access to underlying storage as we're part of the sandbox
|
|
61 |
+ root_directory = self.get_virtual_directory().external_directory
|
|
60 | 62 |
|
61 | 63 |
# Fallback to the sandbox default settings for
|
62 | 64 |
# the cwd and env.
|
... | ... | @@ -316,11 +316,11 @@ class Sandbox(): |
316 | 316 |
def _has_command(self, command, env=None):
|
317 | 317 |
if os.path.isabs(command):
|
318 | 318 |
return os.path.exists(os.path.join(
|
319 |
- self.get_directory(), command.lstrip(os.sep)))
|
|
319 |
+ self._root, command.lstrip(os.sep)))
|
|
320 | 320 |
|
321 | 321 |
for path in env.get('PATH').split(':'):
|
322 | 322 |
if os.path.exists(os.path.join(
|
323 |
- self.get_directory(), path.lstrip(os.sep), command)):
|
|
323 |
+ self._root, path.lstrip(os.sep), command)):
|
|
324 | 324 |
return True
|
325 | 325 |
|
326 | 326 |
return False
|
... | ... | @@ -243,9 +243,8 @@ class ScriptElement(Element): |
243 | 243 |
with self.timed_activity("Staging {} at {}"
|
244 | 244 |
.format(element.name, item['destination']),
|
245 | 245 |
silent_nested=True):
|
246 |
- real_dstdir = os.path.join(sandbox.get_directory(),
|
|
247 |
- item['destination'].lstrip(os.sep))
|
|
248 |
- os.makedirs(os.path.dirname(real_dstdir), exist_ok=True)
|
|
246 |
+ virtual_dstdir = sandbox.get_virtual_directory()
|
|
247 |
+ virtual_dstdir.descend(item['destination'].lstrip(os.sep).split(os.sep), create=True)
|
|
249 | 248 |
element.stage_dependency_artifacts(sandbox, Scope.RUN, path=item['destination'])
|
250 | 249 |
|
251 | 250 |
for item in self.__layout:
|
... | ... | @@ -263,8 +262,8 @@ class ScriptElement(Element): |
263 | 262 |
for dep in element.dependencies(Scope.RUN):
|
264 | 263 |
dep.integrate(sandbox)
|
265 | 264 |
|
266 |
- os.makedirs(os.path.join(sandbox.get_directory(), self.__install_root.lstrip(os.sep)),
|
|
267 |
- exist_ok=True)
|
|
265 |
+ install_root_path_components = self.__install_root.lstrip(os.sep).split(os.sep)
|
|
266 |
+ sandbox.get_virtual_directory().descend(install_root_path_components, create=True)
|
|
268 | 267 |
|
269 | 268 |
def assemble(self, sandbox):
|
270 | 269 |
|