def test_abspath_overlap(self):
     base = "/foo/bar"
     # simple
     self.assertEqual('SAME_AS', realpath_relation("/foo", "/foo"))
     self.assertEqual('SAME_AS', realpath_relation("/", "/"))
     # denormalized
     self.assertEqual('SAME_AS', realpath_relation("/foo/.", "/foo/bar/../"))
     # subdir
     self.assertEqual('PARENT_OF', realpath_relation("/foo", "/foo/bar/baz/bam"))
     self.assertEqual('CHILD_OF', realpath_relation("/foo/bar/baz/bam", "/foo"))
     ## Negatives
     self.assertEqual(None, realpath_relation("/foo", "/bar"))
     self.assertEqual(None, realpath_relation("/foo", "/foo2"))
     self.assertEqual(None, realpath_relation("/foo/bar", "/foo/ba"))
     self.assertEqual(None, realpath_relation("/foo/ba", "/foo/bar/baz"))
     self.assertEqual(None, realpath_relation("/foo/bar/baz", "/foo/ba"))
Exemple #2
0
    def insert_element(self, new_config_elt, merge_strategy='KillAppend'):
        """
        Insert ConfigElement to self.trees, checking for duplicate
        local-name or path first.  In case local_name matches, follow
        given strategy

        - KillAppend (default): remove old element, append new at the end
        - MergeReplace: remove first hit, insert new at that position.
        - MergeKeep: Discard new element

        In case local path matches but local name does not, raise Exception

        :returns: the action performed None, 'Append', 'KillAppend',
        'MergeReplace', 'MergeKeep'
        """
        removals = []
        replaced = False
        for index, loop_elt in enumerate(self.trees):
            # if paths are os.path.realpath, no symlink problems.
            relationship = realpath_relation(loop_elt.get_path(),
                                             new_config_elt.get_path())
            if relationship == 'SAME_AS':
                if os.path.normpath(loop_elt.get_local_name()) != os.path.normpath(new_config_elt.get_local_name()):
                    raise MultiProjectException("Elements with different local_name target the same path: %s, %s" % (loop_elt, new_config_elt))
                else:
                    if (loop_elt == new_config_elt):
                        return None
                    if (merge_strategy == 'MergeReplace' or
                        (merge_strategy == 'KillAppend' and
                         index == len(self.trees) - 1)):
                        self.trees[index] = new_config_elt
                        # keep looping to check for overlap when replacing non-
                        # scm with scm entry
                        replaced = True
                        if (loop_elt.is_vcs_element or not new_config_elt.is_vcs_element):
                            return 'MergeReplace'
                    elif merge_strategy == 'KillAppend':
                        removals.append(loop_elt)
                    elif merge_strategy == 'MergeKeep':
                        return 'MergeKeep'
                    else:
                        raise LookupError(
                            "No such merge strategy: %s" % str(merge_strategy))
            elif ((relationship == 'CHILD_OF' and new_config_elt.is_vcs_element())
                  or (relationship == 'PARENT_OF' and loop_elt.is_vcs_element())):
                # we do not allow any elements to be children of scm elements
                # to allow for parallel updates and because wstool may
                # delete scm folders on update, and thus subfolders can be
                # deleted with their parents
                raise MultiProjectException(
                    "Managed Element paths overlap: %s, %s" % (loop_elt,
                                                               new_config_elt))
        if replaced:
            return 'MergeReplace'
        for loop_elt in removals:
            self.trees.remove(loop_elt)
        self.trees.append(new_config_elt)
        if len(removals) > 0:
            return 'KillAppend'
        return 'Append'
Exemple #3
0
 def test_abspath_overlap(self):
     base = "/foo/bar"
     # simple
     self.assertEqual('SAME_AS', realpath_relation("/foo", "/foo"))
     self.assertEqual('SAME_AS', realpath_relation("/", "/"))
     # denormalized
     self.assertEqual('SAME_AS', realpath_relation("/foo/.",
                                                   "/foo/bar/../"))
     # subdir
     self.assertEqual('PARENT_OF',
                      realpath_relation("/foo", "/foo/bar/baz/bam"))
     self.assertEqual('CHILD_OF',
                      realpath_relation("/foo/bar/baz/bam", "/foo"))
     ## Negatives
     self.assertEqual(None, realpath_relation("/foo", "/bar"))
     self.assertEqual(None, realpath_relation("/foo", "/foo2"))
     self.assertEqual(None, realpath_relation("/foo/bar", "/foo/ba"))
     self.assertEqual(None, realpath_relation("/foo/ba", "/foo/bar/baz"))
     self.assertEqual(None, realpath_relation("/foo/bar/baz", "/foo/ba"))
Exemple #4
0
    def insert_element(self, new_config_elt, merge_strategy='KillAppend'):
        """
        Insert ConfigElement to self.trees, checking for duplicate
        local-name or path first.  In case local_name matches, follow
        given strategy

        - KillAppend (default): remove old element, append new at the end
        - MergeReplace: remove first hit, insert new at that position.
        - MergeKeep: Discard new element

        In case local path matches but local name does not, raise Exception

        :returns: the action performed None, 'Append', 'KillAppend',
        'MergeReplace', 'MergeKeep'
        """
        removals = []
        replaced = False
        for index, loop_elt in enumerate(self.trees):
            # if paths are os.path.realpath, no symlink problems.
            relationship = realpath_relation(loop_elt.get_path(),
                                             new_config_elt.get_path())
            if relationship == 'SAME_AS':
                if os.path.normpath(
                        loop_elt.get_local_name()) != os.path.normpath(
                            new_config_elt.get_local_name()):
                    raise MultiProjectException(
                        "Elements with different local_name target the same path: %s, %s"
                        % (loop_elt, new_config_elt))
                else:
                    if (loop_elt == new_config_elt):
                        return None
                    if (merge_strategy == 'MergeReplace'
                            or (merge_strategy == 'KillAppend'
                                and index == len(self.trees) - 1)):
                        self.trees[index] = new_config_elt
                        # keep looping to check for overlap when replacing non-
                        # scm with scm entry
                        replaced = True
                        if (loop_elt.is_vcs_element
                                or not new_config_elt.is_vcs_element):
                            return 'MergeReplace'
                    elif merge_strategy == 'KillAppend':
                        removals.append(loop_elt)
                    elif merge_strategy == 'MergeKeep':
                        return 'MergeKeep'
                    else:
                        raise LookupError("No such merge strategy: %s" %
                                          str(merge_strategy))
            elif ((relationship == 'CHILD_OF'
                   and new_config_elt.is_vcs_element()) or
                  (relationship == 'PARENT_OF' and loop_elt.is_vcs_element())):
                # we do not allow any elements to be children of scm elements
                # to allow for parallel updates and because wstool may
                # delete scm folders on update, and thus subfolders can be
                # deleted with their parents
                raise MultiProjectException(
                    "Managed Element paths overlap: %s, %s" %
                    (loop_elt, new_config_elt))
        if replaced:
            return 'MergeReplace'
        for loop_elt in removals:
            self.trees.remove(loop_elt)
        self.trees.append(new_config_elt)
        if len(removals) > 0:
            return 'KillAppend'
        return 'Append'