docs: def GlobForPaths(self,
                     paths,
                     pathtype="OS",
                     root_path=None,
                     process_non_regular_files=False,
                     collect_ext_attrs=False):
      """Starts the Glob.
  
      This is the main entry point for this flow mixin.
  
      First we convert the pattern into regex components, and then we
      interpolate each component. Finally, we generate a cartesian product of all
      combinations.
  
      Args:
        paths: A list of GlobExpression instances.
        pathtype: The pathtype to use for creating pathspecs.
        root_path: A pathspec where to start searching from.
        process_non_regular_files: Work with all kinds of files - not only with
          regular ones.
        collect_ext_attrs: Whether to gather information about file extended
          attributes.
      """
      patterns = []
  
      if not paths:
        # Nothing to do.
        return
  
      self.state.pathtype = pathtype
      self.state.root_path = root_path
      self.state.process_non_regular_files = process_non_regular_files
      self.state.collect_ext_attrs = collect_ext_attrs
  
      # Transform the patterns by substitution of client attributes. When the
      # client has multiple values for an attribute, this generates multiple
      # copies of the pattern, one for each variation. e.g.:
      # /home/%%Usernames%%/* -> [ /home/user1/*, /home/user2/* ]
      for path in paths:
        patterns.extend(
            path.Interpolate(knowledge_base=self.client_knowledge_base))
  
      # Sort the patterns so that if there are files whose paths conflict with
      # directory paths, the files get handled after the conflicting directories
      # have been added to the component tree.
      patterns.sort(key=len, reverse=True)
  
      # Expand each glob pattern into a list of components. A component is either
      # a wildcard or a literal component.
      # e.g. /usr/lib/*.exe -> ['/usr/lib', '.*.exe']
  
      # We build a tree for each component such that duplicated components are
      # merged. We do not need to reissue the same client requests for the same
      # components. For example, the patterns:
      # '/home/%%Usernames%%*' -> {'/home/': {
      #      'syslog.*\\Z(?ms)': {}, 'test.*\\Z(?ms)': {}}}
      # Note: The component tree contains serialized pathspecs in dicts.
      for pattern in patterns:
        # The root node.
        curr_node = self.state.component_tree
  
        components = self.ConvertGlobIntoPathComponents(pattern)
        for i, curr_component in enumerate(components):
          is_last_component = i == len(components) - 1
          next_node = curr_node.get(curr_component.SerializeToString(), {})
          if is_last_component and next_node:
            # There is a conflicting directory already existing in the tree.
            # Replace the directory node with a node representing this file.
            curr_node[curr_component.SerializeToString()] = {}
          else:
            curr_node = curr_node.setdefault(curr_component.SerializeToString(),
                                             {})
  
      root_path = next(iterkeys(self.state.component_tree))
      self.CallStateInline(
          messages=[None],
          next_state="ProcessEntry",
          request_data=dict(component_path=[root_path]))