cpg1111/maestro

View on GitHub
pipeline/tree.go

Summary

Maintainability
A
0 mins
Test Coverage
/*
Copyright 2016 Christian Grabowski All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package pipeline

import (
    "errors"
    "log"

    git "gopkg.in/libgit2/git2go.v24"
)

// DepTree is a dependency tree to determine whether or not to build services
type DepTree struct {
    CurrNode *DepService
}

// TraverseTree traverses a dependency tree
func TraverseTree(depSrv *DepService, repo *git.Repository, lastBuildCommit, currBuildCommit *string) error {
    if depSrv == nil {
        return errors.New("Service is nil in tree")
    }
    shouldBuild, err := depSrv.build.ShouldBuild(repo, lastBuildCommit, currBuildCommit)
    if err != nil {
        return err
    }
    for i := range depSrv.Children {
        depSrv.Children[i].build.shouldBuild = shouldBuild
        err = TraverseTree(depSrv.Children[i], repo, lastBuildCommit, currBuildCommit)
        if err != nil {
            return err
        }
    }
    return nil
}

// DepService represents a service in the tree
type DepService struct {
    build    *Service
    Parent   *DepService
    Children map[string]*DepService
}

func dependsOnChild(child, parent *DepService) int {
    for j := range child.build.conf.DependsOn {
        if _, ok := parent.Children[child.build.conf.DependsOn[j]]; ok {
            return j
        }
    }
    return -1
}

func getDependencies(depSrv *DepService, tree *DepTree, created map[string]*DepService, proj *Project) {
    for j := range depSrv.build.conf.DependsOn {
        if _, ok := created[depSrv.build.conf.DependsOn[j]]; ok {
            youngerParentIndex := dependsOnChild(depSrv, created[depSrv.build.conf.DependsOn[j]])
            if youngerParentIndex > -1 {
                depSrv.Parent = created[depSrv.build.conf.DependsOn[j]].Children[depSrv.build.conf.DependsOn[youngerParentIndex]]
                depSrv.Parent.Children[depSrv.build.conf.Name] = depSrv
            } else {
                depSrv.Parent = created[depSrv.build.conf.DependsOn[j]]
                if _, ok := depSrv.Parent.Children[depSrv.build.conf.Name]; !ok {
                    depSrv.Parent.Children[depSrv.build.conf.Name] = depSrv
                }
            }
        } else {
            parent := &DepService{
                build:    proj.Services[depSrv.build.conf.DependsOn[j]],
                Children: make(map[string]*DepService),
            }
            depSrv.Parent = parent
            created[depSrv.build.conf.DependsOn[j]] = parent
            parent.Children[depSrv.build.conf.Name] = depSrv
            created[depSrv.build.conf.Name] = depSrv
            if len(parent.build.conf.DependsOn) > 0 {
                getDependencies(parent, tree, created, proj)
            } else if tree.CurrNode == nil {
                tree.CurrNode = parent
            } else if _, ok := tree.CurrNode.Children[parent.build.conf.Name]; !ok {
                tree.CurrNode.Children[parent.build.conf.Name] = parent
            }
        }
    }
}

// NewTreeList returns a list of dependency trees
func NewTreeList(proj *Project) (newTree *DepTree) {
    created := make(map[string]*DepService)
    newTree = &DepTree{CurrNode: nil}
    for i := range proj.Services {
        log.Println("Finding a spot in the tree for", proj.Services[i].conf.Name)
        if _, ok := created[proj.Services[i].conf.Name]; ok {
            continue
        }
        depSrv := &DepService{build: proj.Services[i], Children: make(map[string]*DepService)}
        if len(depSrv.build.conf.DependsOn) != 0 {
            getDependencies(depSrv, newTree, created, proj)
        } else if newTree.CurrNode == nil {
            newTree.CurrNode = depSrv
        } else {
            newTree.CurrNode.Children[depSrv.build.conf.Name] = depSrv
        }
    }
    return
}