Jonathan Maw pushed to branch jonathan/workspace-fragment-guess-element at BuildStream / buildstream
Commits:
- 
8c6ddc01
by Jonathan Maw at 2018-11-14T16:54:51Z
4 changed files:
Changes:
| ... | ... | @@ -31,7 +31,7 @@ from ._exceptions import LoadError, LoadErrorReason, BstError | 
| 31 | 31 |  from ._message import Message, MessageType
 | 
| 32 | 32 |  from ._profile import Topics, profile_start, profile_end
 | 
| 33 | 33 |  from ._artifactcache import ArtifactCache
 | 
| 34 | -from ._workspaces import Workspaces
 | |
| 34 | +from ._workspaces import Workspaces, WorkspaceLocals
 | |
| 35 | 35 |  from .plugin import _plugin_lookup
 | 
| 36 | 36 |  | 
| 37 | 37 |  | 
| ... | ... | @@ -118,6 +118,7 @@ class Context(): | 
| 118 | 118 |          self._projects = []
 | 
| 119 | 119 |          self._project_overrides = {}
 | 
| 120 | 120 |          self._workspaces = None
 | 
| 121 | +        self._workspace_locals = WorkspaceLocals()
 | |
| 121 | 122 |          self._log_handle = None
 | 
| 122 | 123 |          self._log_filename = None
 | 
| 123 | 124 |          self.config_cache_quota = 'infinity'
 | 
| ... | ... | @@ -272,6 +273,9 @@ class Context(): | 
| 272 | 273 |      def get_workspaces(self):
 | 
| 273 | 274 |          return self._workspaces
 | 
| 274 | 275 |  | 
| 276 | +    def get_workspace_locals(self):
 | |
| 277 | +        return self._workspace_locals
 | |
| 278 | + | |
| 275 | 279 |      # get_overrides():
 | 
| 276 | 280 |      #
 | 
| 277 | 281 |      # Fetch the override dictionary for the active project. This returns
 | 
| ... | ... | @@ -40,7 +40,6 @@ from .element import Element | 
| 40 | 40 |  from ._message import Message, MessageType
 | 
| 41 | 41 |  from ._includes import Includes
 | 
| 42 | 42 |  from ._platform import Platform
 | 
| 43 | -from ._workspaces import WorkspaceLocal
 | |
| 44 | 43 |  | 
| 45 | 44 |  | 
| 46 | 45 |  # Project Configuration file
 | 
| ... | ... | @@ -678,8 +677,9 @@ class Project(): | 
| 678 | 677 |          workspace_element = ""
 | 
| 679 | 678 |          project_directory = utils._search_upward_for_file(directory, _PROJECT_CONF_FILE)
 | 
| 680 | 679 |          if not project_directory:
 | 
| 681 | -            workspace_local = WorkspaceLocal.load(directory)
 | |
| 682 | -            if workspace_local:
 | |
| 680 | +            workspace_locals = self._context.get_workspace_locals()
 | |
| 681 | +            workspace_local = workspace_locals.get(directory)
 | |
| 682 | +            if workspace_local.has_projects():
 | |
| 683 | 683 |                  project_directory = workspace_local.get_default_path()
 | 
| 684 | 684 |                  workspace_element = workspace_local.get_default_element()
 | 
| 685 | 685 |              else:
 | 
| ... | ... | @@ -32,7 +32,6 @@ from ._exceptions import StreamError, ImplError, BstError, set_last_task_error | 
| 32 | 32 |  from ._message import Message, MessageType
 | 
| 33 | 33 |  from ._scheduler import Scheduler, SchedStatus, TrackQueue, FetchQueue, BuildQueue, PullQueue, PushQueue
 | 
| 34 | 34 |  from ._pipeline import Pipeline, PipelineSelection
 | 
| 35 | -from ._workspaces import WorkspaceLocal
 | |
| 36 | 35 |  from . import utils, _yaml, _site
 | 
| 37 | 36 |  from . import Scope, Consistency
 | 
| 38 | 37 |  | 
| ... | ... | @@ -517,8 +516,9 @@ class Stream(): | 
| 517 | 516 |              with target.timed_activity("Staging sources to {}".format(directory)):
 | 
| 518 | 517 |                  target._open_workspace()
 | 
| 519 | 518 |  | 
| 519 | +        workspace_locals = self._context.get_workspace_locals()
 | |
| 520 | 520 |          project = self._context.get_toplevel_project()
 | 
| 521 | -        workspace_local = WorkspaceLocal.create(directory, project.directory, target._get_full_name())
 | |
| 521 | +        workspace_local = workspace_locals.add(directory, project.directory, target._get_full_name())
 | |
| 522 | 522 |          workspace_local.write()
 | 
| 523 | 523 |  | 
| 524 | 524 |          workspaces.save_config()
 | 
| ... | ... | @@ -546,11 +546,8 @@ class Stream(): | 
| 546 | 546 |                      raise StreamError("Could not remove  '{}': {}"
 | 
| 547 | 547 |                                        .format(workspace.get_absolute_path(), e)) from e
 | 
| 548 | 548 |          else:
 | 
| 549 | -            # NOTE: After future work on workspace fragments, closing a workspace
 | |
| 550 | -            #       only deletes the file if no projects are using it.
 | |
| 551 | -            workspace_local = WorkspaceLocal.load(workspace.get_absolute_path())
 | |
| 552 | -            if workspace_local:
 | |
| 553 | -                workspace_local.delete()
 | |
| 549 | +            workspace_locals = self._context.get_workspace_locals()
 | |
| 550 | +            workspace_locals.remove(workspace.get_absolute_path())
 | |
| 554 | 551 |  | 
| 555 | 552 |          # Delete the workspace and save the configuration
 | 
| 556 | 553 |          workspaces.delete_workspace(element_name)
 | 
| ... | ... | @@ -48,6 +48,9 @@ class WorkspaceLocal(): | 
| 48 | 48 |          if project_path:
 | 
| 49 | 49 |              self._add_project(project_path, element_name)
 | 
| 50 | 50 |  | 
| 51 | +    def has_projects(self):
 | |
| 52 | +        return True if self._projects else False
 | |
| 53 | + | |
| 51 | 54 |      # get_default_path()
 | 
| 52 | 55 |      #
 | 
| 53 | 56 |      # Retrieves the default path to a project.
 | 
| ... | ... | @@ -103,22 +106,6 @@ class WorkspaceLocal(): | 
| 103 | 106 |  | 
| 104 | 107 |          return workspace_local
 | 
| 105 | 108 |  | 
| 106 | -    # create()
 | |
| 107 | -    #
 | |
| 108 | -    # Creates a new WorkspaceLocal
 | |
| 109 | -    #
 | |
| 110 | -    # Args:
 | |
| 111 | -    #    directory (str): The directory that the workspace exists in
 | |
| 112 | -    #    project_path (str): The path to the project to store
 | |
| 113 | -    #    element_name (str): The name of the element within the project
 | |
| 114 | -    #
 | |
| 115 | -    # Returns:
 | |
| 116 | -    #    (WorkspaceLocal): The created WorkspaceLocal
 | |
| 117 | -    @classmethod
 | |
| 118 | -    def create(cls, directory, project_path, element_name):
 | |
| 119 | -        # NOTE: In later changes, Load WorkspaceLocal if it exists, and maybe add project_path to it
 | |
| 120 | -        return cls(directory, project_path, element_name)
 | |
| 121 | - | |
| 122 | 109 |      # load()
 | 
| 123 | 110 |      #
 | 
| 124 | 111 |      # Loads the WorkspaceLocal for a given directory. This directory may be a
 | 
| ... | ... | @@ -146,15 +133,6 @@ class WorkspaceLocal(): | 
| 146 | 133 |          os.makedirs(self._directory, exist_ok=True)
 | 
| 147 | 134 |          _yaml.dump(self.to_dict(), self._get_filename())
 | 
| 148 | 135 |  | 
| 149 | -    # delete()
 | |
| 150 | -    #
 | |
| 151 | -    # Deletes the WorkspaceLocal from disk, if it exists.
 | |
| 152 | -    def delete(self):
 | |
| 153 | -        try:
 | |
| 154 | -            os.unlink(self._get_filename())
 | |
| 155 | -        except FileNotFoundError:
 | |
| 156 | -            pass
 | |
| 157 | - | |
| 158 | 136 |      # search_for_dir()
 | 
| 159 | 137 |      #
 | 
| 160 | 138 |      # Returns the directory that contains the workspace local file,
 | 
| ... | ... | @@ -167,9 +145,47 @@ class WorkspaceLocal(): | 
| 167 | 145 |          return os.path.join(self._directory, WORKSPACE_LOCAL_FILE)
 | 
| 168 | 146 |  | 
| 169 | 147 |      def _add_project(self, project_path, element_name):
 | 
| 148 | +        assert (project_path and element_name)
 | |
| 170 | 149 |          self._projects.append({'project-path': project_path, 'element-name': element_name})
 | 
| 171 | 150 |  | 
| 172 | 151 |  | 
| 152 | +# WorkspaceLocals()
 | |
| 153 | +#
 | |
| 154 | +# A class to manage workspace local data for multiple workspaces.
 | |
| 155 | +#
 | |
| 156 | +class WorkspaceLocals():
 | |
| 157 | +    def __init__(self):
 | |
| 158 | +        self._locals = {}  # Mapping of a workspace directory to its WorkspaceLocal
 | |
| 159 | + | |
| 160 | +    def get(self, directory):
 | |
| 161 | +        # NOTE: Later, this will load any WorkspaceLocal found from directory
 | |
| 162 | +        try:
 | |
| 163 | +            local = self._locals[directory]
 | |
| 164 | +        except KeyError:
 | |
| 165 | +            local = WorkspaceLocal.load(directory)
 | |
| 166 | +            if not local:
 | |
| 167 | +                local = WorkspaceLocal(directory)
 | |
| 168 | +            self._locals[directory] = local
 | |
| 169 | + | |
| 170 | +        return local
 | |
| 171 | + | |
| 172 | +    def add(self, directory, project_path='', element_name=''):
 | |
| 173 | +        local = self.get(directory)
 | |
| 174 | +        if project_path:
 | |
| 175 | +            local._add_project(project_path, element_name)
 | |
| 176 | +        return local
 | |
| 177 | + | |
| 178 | +    def remove(self, directory, project_path='', element_name=''):
 | |
| 179 | +        # NOTE: project_path and element_name will only be used when I implement
 | |
| 180 | +        #       multiple owners of a workspace
 | |
| 181 | +        local = self.get(directory)
 | |
| 182 | +        path = local._get_filename()
 | |
| 183 | +        try:
 | |
| 184 | +            os.unlink(path)
 | |
| 185 | +        except FileNotFoundError:
 | |
| 186 | +            pass
 | |
| 187 | + | |
| 188 | + | |
| 173 | 189 |  # Workspace()
 | 
| 174 | 190 |  #
 | 
| 175 | 191 |  # An object to contain various helper functions and data required for
 | 
