func parentsRemoved(parents []dag.Node, record *db.BuildRecord) bool { parentset := make(map[string]bool) for _, parent := range parents { parentset[parent.Name()] = true } for _, name := range record.Parents() { if !parentset[name] { return true } } return false }
// Inspect node and its parents to see if we need to build it. Return // build=true if we should build it, tainted=true if we should skip // building this node due to upstream failure. Return non-nil err if // there were unexpected node errors (error checking existence or // change status). func (self *BuildState) considerNode(node dag.Node) ( build bool, tainted bool, err error) { var exists, changed bool exists, err = node.Exists() // obvious rebuild (unless tainted) if err != nil { return } missing := !exists var record *db.BuildRecord if !missing { // skip DB lookup for missing nodes: the only thing that will // stop us from rebuilding them is a failed parent, and that // check comes later record, err = self.db.LookupNode(node.Name()) if err != nil { return } if record != nil { log.Debug(log.BUILD, "old parents of %s:", node) log.DebugDump(log.BUILD, record) } } build = missing parents := self.graph.ParentNodes(node) // Check if any of node's former parents have been removed. if !build && record != nil { build = parentsRemoved(parents, record) } for _, parent := range parents { pstate := parent.State() if pstate == dag.FAILED || pstate == dag.TAINTED { build = false tainted = true return // no further inspection required } var oldsig []byte if record != nil { oldsig = record.SourceSignature(parent.Name()) } if oldsig == nil { // New parent for this node: rebuild unless another // parent is failed/tainted. build = true } if build { continue } changed, err = self.parentChanged(parent, pstate, oldsig) if err != nil { return } if changed { // Do NOT return here: we need to continue inspecting // parents to make sure they don't taint this node with // upstream failure. build = true } } return }