[Notes] [Git][BuildStream/buildstream][jonathan/workspace-fragment-multi-project] Implement basic handling of multiple projects to a single workspace



Title: GitLab

Jonathan Maw pushed to branch jonathan/workspace-fragment-multi-project at BuildStream / buildstream

Commits:

2 changed files:

Changes:

  • buildstream/_stream.py
    ... ... @@ -568,6 +568,9 @@ class Stream():
    568 568
                 self._message(MessageType.INFO, "Creating workspace for element {}"
    
    569 569
                               .format(target.name))
    
    570 570
     
    
    571
    +            # Ensure the WorkspaceProject is loaded before we delete it
    
    572
    +            workspaces.get_workspace_project(directory)
    
    573
    +
    
    571 574
                 workspace = workspaces.get_workspace(target._get_full_name())
    
    572 575
                 if workspace:
    
    573 576
                     workspaces.delete_workspace(target._get_full_name())
    
    ... ... @@ -582,7 +585,7 @@ class Stream():
    582 585
                         todo_elements = "\nDid not try to create workspaces for " + todo_elements
    
    583 586
                     raise StreamError("Failed to create workspace directory: {}".format(e) + todo_elements) from e
    
    584 587
     
    
    585
    -            workspaces.create_workspace(target, directory, checkout=not no_checkout)
    
    588
    +            workspaces.create_workspace(target, directory, checkout=not no_checkout, append=force)
    
    586 589
                 self._message(MessageType.INFO, "Created a workspace for element: {}"
    
    587 590
                               .format(target._get_full_name()))
    
    588 591
     
    
    ... ... @@ -664,8 +667,13 @@ class Stream():
    664 667
                         raise StreamError("Could not remove  '{}': {}"
    
    665 668
                                           .format(workspace_path, e)) from e
    
    666 669
     
    
    667
    -            workspaces.delete_workspace(element._get_full_name())
    
    668
    -            workspaces.create_workspace(element, workspace_path, checkout=True)
    
    670
    +            # Ensure the WorkspaceProject is in the cache before it gets deleted
    
    671
    +            workspaces.get_workspace_project(workspace_path)
    
    672
    +
    
    673
    +            workspaces.delete_workspace(element._get_full_name(),
    
    674
    +                                        preserve_workspace_project=True)
    
    675
    +            workspaces.create_workspace(element, workspace_path, checkout=True,
    
    676
    +                                        preserve_workspace_project=True)
    
    669 677
     
    
    670 678
                 self._message(MessageType.INFO,
    
    671 679
                               "Reset workspace for {} at: {}".format(element.name,
    

  • buildstream/_workspaces.py
    ... ... @@ -143,8 +143,38 @@ class WorkspaceProject():
    143 143
         #    element_name (str): The name of the element that the workspace belongs to.
    
    144 144
         #
    
    145 145
         def add_project(self, project_path, element_name):
    
    146
    -        assert (project_path and element_name)
    
    147
    -        self._projects.append({'project-path': project_path, 'element-name': element_name})
    
    146
    +        # TODO: Decide whether to raise an exception if the project already exists.
    
    147
    +        project = {'project-path': project_path, 'element-name': element_name}
    
    148
    +        if project not in self._projects:
    
    149
    +            self._projects.append(project)
    
    150
    +
    
    151
    +    # set_project()
    
    152
    +    #
    
    153
    +    # Sets the project to only contain the project_path and element_name specified.
    
    154
    +    #
    
    155
    +    # Args:
    
    156
    +    #    project_path (str): the path to the project that opened the workspace.
    
    157
    +    #    element_name (str): the name of the element that the workspace belongs to.
    
    158
    +    #
    
    159
    +    def set_project(self, project_path, element_name):
    
    160
    +        self._projects = [{'project-path': project_path, 'element-name': element_name}]
    
    161
    +
    
    162
    +    # remove_project()
    
    163
    +    #
    
    164
    +    # Removes the first project entry that matches the project_path and element_name
    
    165
    +    def remove_project(self, project_path, element_name):
    
    166
    +        # NOTE: This will need revisiting if projects' data format changes
    
    167
    +        # TODO: Figure out what to do if there is no project for those parameters
    
    168
    +        self._projects.remove({'project-path': project_path, 'element-name': element_name})
    
    169
    +
    
    170
    +    # has_projects()
    
    171
    +    #
    
    172
    +    # Returns whether there are any projects in this WorkspaceProject
    
    173
    +    #
    
    174
    +    # Returns:
    
    175
    +    #    (bool): True if there are any projects, or False if there aren't any
    
    176
    +    def has_projects(self):
    
    177
    +        return any(self._projects)
    
    148 178
     
    
    149 179
     
    
    150 180
     # WorkspaceProjectCache()
    
    ... ... @@ -186,17 +216,21 @@ class WorkspaceProjectCache():
    186 216
         #    directory (str): The directory to search for a WorkspaceProject.
    
    187 217
         #    project_path (str): The path to the project that refers to this workspace
    
    188 218
         #    element_name (str): The element in the project that was refers to this workspace
    
    219
    +    #    append (bool): Whether the project_path and element_name should be appended
    
    189 220
         #
    
    190 221
         # Returns:
    
    191 222
         #    (WorkspaceProject): The WorkspaceProject that was found for that directory.
    
    192 223
         #
    
    193
    -    def add(self, directory, project_path, element_name):
    
    224
    +    def add(self, directory, project_path, element_name, *, append):
    
    194 225
             workspace_project = self.get(directory)
    
    195 226
             if not workspace_project:
    
    196 227
                 workspace_project = WorkspaceProject(directory)
    
    197 228
                 self._projects[directory] = workspace_project
    
    198 229
     
    
    199
    -        workspace_project.add_project(project_path, element_name)
    
    230
    +        if append:
    
    231
    +            workspace_project.add_project(project_path, element_name)
    
    232
    +        else:
    
    233
    +            workspace_project.set_project(project_path, element_name)
    
    200 234
             return workspace_project
    
    201 235
     
    
    202 236
         # remove()
    
    ... ... @@ -210,17 +244,26 @@ class WorkspaceProjectCache():
    210 244
         #
    
    211 245
         # Args:
    
    212 246
         #    directory (str): The directory to search for a WorkspaceProject.
    
    247
    +    #    project_path (str): the path to the project that should be removed.
    
    248
    +    #    element_name (str): the name of the element in the project that should be removed.
    
    213 249
         #
    
    214
    -    def remove(self, directory):
    
    250
    +    def remove(self, directory, project_path, element_name):
    
    215 251
             workspace_project = self.get(directory)
    
    216 252
             if not workspace_project:
    
    217 253
                 raise LoadError(LoadErrorReason.MISSING_FILE,
    
    218 254
                                 "Failed to find a {} file to remove".format(WORKSPACE_PROJECT_FILE))
    
    219
    -        path = workspace_project.get_filename()
    
    220
    -        try:
    
    221
    -            os.unlink(path)
    
    222
    -        except FileNotFoundError:
    
    223
    -            pass
    
    255
    +
    
    256
    +        workspace_project.remove_project(project_path, element_name)
    
    257
    +
    
    258
    +        if workspace_project.has_projects():
    
    259
    +            workspace_project.write()
    
    260
    +        else:
    
    261
    +            # Remove the WorkspaceProject file if it's now empty
    
    262
    +            path = workspace_project.get_filename()
    
    263
    +            try:
    
    264
    +                os.unlink(path)
    
    265
    +            except FileNotFoundError:
    
    266
    +                pass
    
    224 267
     
    
    225 268
     
    
    226 269
     # Workspace()
    
    ... ... @@ -429,8 +472,10 @@ class Workspaces():
    429 472
         #    target (Element) - The element to create a workspace for
    
    430 473
         #    path (str) - The path in which the workspace should be kept
    
    431 474
         #    checkout (bool): Whether to check-out the element's sources into the directory
    
    475
    +    #    append (bool): Whether the WorkspaceProject file should append this project
    
    476
    +    #    preserve_workspace_project (bool): Whether the WorkspaceProject should be altered
    
    432 477
         #
    
    433
    -    def create_workspace(self, target, path, *, checkout):
    
    478
    +    def create_workspace(self, target, path, *, checkout, append, preserve_workspace_project=False):
    
    434 479
             element_name = target._get_full_name()
    
    435 480
             project_dir = self._toplevel_project.directory
    
    436 481
             if path.startswith(project_dir):
    
    ... ... @@ -444,7 +489,11 @@ class Workspaces():
    444 489
                 with target.timed_activity("Staging sources to {}".format(path)):
    
    445 490
                     target._open_workspace()
    
    446 491
     
    
    447
    -        workspace_project = self._workspace_project_cache.add(path, project_dir, element_name)
    
    492
    +        if preserve_workspace_project:
    
    493
    +            workspace_project = self._workspace_project_cache.get(path)
    
    494
    +        else:
    
    495
    +            workspace_project = self._workspace_project_cache.add(path, project_dir, element_name, append=append)
    
    496
    +
    
    448 497
             project_file_path = workspace_project.get_filename()
    
    449 498
     
    
    450 499
             if os.path.exists(project_file_path):
    
    ... ... @@ -469,6 +518,21 @@ class Workspaces():
    469 518
                 return None
    
    470 519
             return self._workspaces[element_name]
    
    471 520
     
    
    521
    +    # get_workspace_project()
    
    522
    +    #
    
    523
    +    # Returns a WorkspaceProject for a given directory, retrieving from the cache if
    
    524
    +    # present.
    
    525
    +    #
    
    526
    +    # Args:
    
    527
    +    #    directory (str): The directory to search for a WorkspaceProject.
    
    528
    +    #
    
    529
    +    # Returns:
    
    530
    +    #    (WorkspaceProject): The WorkspaceProject that was found for that directory.
    
    531
    +    #    or      (NoneType): None, if no WorkspaceProject can be found.
    
    532
    +    #
    
    533
    +    def get_workspace_project(self, directory):
    
    534
    +        return self._workspace_project_cache.get(directory)
    
    535
    +
    
    472 536
         # update_workspace()
    
    473 537
         #
    
    474 538
         # Update the datamodel with a new Workspace instance
    
    ... ... @@ -498,20 +562,23 @@ class Workspaces():
    498 562
         #
    
    499 563
         # Args:
    
    500 564
         #    element_name (str) - The element name whose workspace to delete
    
    565
    +    #    preserve_workspace_project (bool): Whether the WorkspaceProject should be altered
    
    501 566
         #
    
    502
    -    def delete_workspace(self, element_name):
    
    567
    +    def delete_workspace(self, element_name, preserve_workspace_project=False):
    
    503 568
             workspace = self.get_workspace(element_name)
    
    504 569
             del self._workspaces[element_name]
    
    505 570
     
    
    506
    -        # Remove from the cache if it exists
    
    507
    -        try:
    
    508
    -            self._workspace_project_cache.remove(workspace.get_absolute_path())
    
    509
    -        except LoadError as e:
    
    510
    -            # We might be closing a workspace with a deleted directory
    
    511
    -            if e.reason == LoadErrorReason.MISSING_FILE:
    
    512
    -                pass
    
    513
    -            else:
    
    514
    -                raise
    
    571
    +        if not preserve_workspace_project:
    
    572
    +            # Remove from the cache if it exists
    
    573
    +            project_dir = self._toplevel_project.directory
    
    574
    +            try:
    
    575
    +                self._workspace_project_cache.remove(workspace.get_absolute_path(), project_dir, element_name)
    
    576
    +            except LoadError as e:
    
    577
    +                # We might be closing a workspace with a deleted directory
    
    578
    +                if e.reason == LoadErrorReason.MISSING_FILE:
    
    579
    +                    pass
    
    580
    +                else:
    
    581
    +                    raise
    
    515 582
     
    
    516 583
         # save_config()
    
    517 584
         #
    



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]