func mergeOrder()

in cmd/hub/compose/elaborate.go [1025:1107]


func mergeOrder(parent, child []string) []string {
	overridesFromChild := make([]int, 0, len(child))
	overridesToParent := make([]int, 0, len(child))
	prevOverridesToParent := 0
	for i, component := range child {
		for j, exist := range parent {
			if component == exist {
				if j < prevOverridesToParent {
					log.Fatalf("Component `%s` must come after `%s` in child stack `lifecycle.order` - as defined by parent stack (fromStack)",
						parent[prevOverridesToParent], component)
				}
				prevOverridesToParent = j
				overridesFromChild = append(overridesFromChild, i)
				overridesToParent = append(overridesToParent, j)
				break
			}
		}
	}

	if config.Trace {
		log.Printf("Lifecycle order overrides to parent indices: %v", overridesToParent)
		log.Printf("Lifecycle order overrides from child indices: %v", overridesFromChild)
	}

	order := make([]string, 0, len(parent)+len(child))
	if len(overridesFromChild) == 0 {
		order = append(order, parent...)
		order = append(order, child...)
		return order
	}

	relative := func(indices []int) {
		prev := 0
		off := 0
		for i, index := range indices {
			indices[i] = index - prev - off
			prev = index
			off = 1
		}
	}

	relative(overridesToParent)
	relative(overridesFromChild)
	if config.Trace {
		log.Printf("Lifecycle order overrides to parent relative indices: %v", overridesToParent)
		log.Printf("Lifecycle order overrides from child relative indices: %v", overridesFromChild)
	}

	parentBlocks := make([][]string, 0, len(child))
	for _, cutAt := range overridesToParent {
		parentBlocks = append(parentBlocks, parent[:cutAt])
		if cutAt == len(parent)-1 {
			parent = []string{}
		} else {
			parent = parent[cutAt+1:]
		}
	}
	parentBlocks = append(parentBlocks, parent)
	if config.Trace {
		log.Printf("Lifecycle order overrides parent blocks: %v", parentBlocks)
	}

	childBlocks := make([][]string, 0, len(child))
	for _, cutAt := range overridesFromChild {
		childBlocks = append(childBlocks, child[:cutAt+1])
		if cutAt == len(child) {
			child = []string{}
		} else {
			child = child[cutAt+1:]
		}
	}
	childBlocks = append(childBlocks, child)
	if config.Trace {
		log.Printf("Lifecycle order overrides child blocks: %v", childBlocks)
	}

	for i := range parentBlocks {
		order = append(order, parentBlocks[i]...)
		order = append(order, childBlocks[i]...)
	}

	return order
}