func()

in gomod/module_tree.go [47:112]


func (t *ModuleTree) Insert(modulePath string, attributes ...string) (newNode *ModuleTreeNode, err error) {
	moduleRelPath := modulePath
	if t.options.RootPath != "" {
		moduleRelPath, err = filepath.Rel(t.options.RootPath, modulePath)
		if err != nil {
			return nil, fmt.Errorf("module %q is not nested within %q, %w",
				modulePath, t.options.RootPath, err)
		}
	}

	if m := t.Get(moduleRelPath); m != nil {
		return nil, fmt.Errorf("module already exists with relative path, %v, %v",
			modulePath, moduleRelPath)
	}

	// search tree for nodes that have the prefix of this node, when they are
	// found walk down to the next layer to find the next node with a more
	// specific prefix.
	nodes := &t.subModules
	for {
		var nextNodes *[]*ModuleTreeNode
		for _, m := range *nodes {
			if m.AncestorOf(moduleRelPath) {
				nextNodes = &m.subModules
				break
			}
		}

		// Walk the module tree until there is no more direct ancestors. Then
		// insert the module at that layer. If the new module is it self an
		// ancestor of some other nodes at this layer, re-parent the children
		// nodes.
		if nextNodes == nil {
			// Copy attributes to ensure list cannot be mutated outside of the node.
			if len(attributes) != 0 {
				attributes = append([]string{}, attributes...)
			}

			newNode = &ModuleTreeNode{
				absPath:    modulePath,
				relPath:    moduleRelPath,
				attributes: attributes,
			}

			// Before adding the new node to the parent, check if there are any
			// existing sub modules of this parent have this new node as their
			// parent.
			for i := 0; i < len(*nodes); i++ {
				if !newNode.AncestorOf((*nodes)[i].Path()) {
					continue
				}

				newNode.subModules = append(newNode.subModules, (*nodes)[i])
				sort.Sort(sortableModuleTreeNodes(newNode.subModules))
				*nodes = cutSubModule(*nodes, i)
				i--
			}

			*nodes = append(*nodes, newNode)
			sort.Sort(sortableModuleTreeNodes(*nodes))
			return newNode, nil
		}

		nodes = nextNodes
	}
}