示例#1
0
文件: build.go 项目: sbinet/fubsy
// panic if node is in an impossible state for starting its visit
func checkInitialState(node dag.Node) {
	if node.State() != dag.UNKNOWN {
		// we just skipped SOURCE nodes, the other states are only set
		// while visiting a node, and we should only visit each node
		// once
		panic(fmt.Sprintf(
			"visiting node %v, state = %s (should be UNKNOWN)",
			node, node.State()))
	}
}
示例#2
0
文件: build.go 项目: sbinet/fubsy
// Build the specified node (caller has determined that it should be
// built and can be built). On failure, report the error (e.g. to the
// console, a GUI window, ...) and return false. On success, return
// true.
func (self *BuildState) buildNode(node dag.Node, builderr *BuildError) bool {
	rule := node.BuildRule()
	log.Verbose("building node %s, action=%s\n", node, rule.ActionString())
	node.SetState(dag.BUILDING)
	builderr.attempts++
	targets, errs := rule.Execute()
	if len(errs) > 0 {
		// Normal, everyday build failure: report the precise problem
		// immediately, and accumulate summary info in the caller.
		for _, tnode := range targets {
			tnode.SetState(dag.FAILED)
		}
		self.reportFailure(errs)
		builderr.addFailure(node)
		return false
	}
	for _, tnode := range targets {
		tnode.SetState(dag.BUILT)
	}
	return true
}
示例#3
0
文件: build.go 项目: sbinet/fubsy
func (self *BuildState) parentChanged(
	parent dag.Node, pstate dag.NodeState, oldsig []byte) (
	bool, error) {

	var cursig []byte
	var err error
	if !(pstate == dag.SOURCE || pstate == dag.BUILT || self.checkAll()) {
		// parent is an intermediate target that has not been built in
		// the current run. We don't want the expense of calling
		// Signature() for target nodes, because people don't normally
		// modify targets behind their build tool's back. But it might
		// have been modified by a previous build, in which case we'll
		// use the signature previously recorded for parent *as a
		// target*. This can still be fooled by modifying intermediate
		// targets behind Fubsy's back, but that's what --check-all is
		// for.
		precord, err := self.db.LookupNode(parent.Name())
		if err != nil {
			return false, err
		}
		if precord != nil {
			cursig = precord.TargetSignature()
		}
	}

	if cursig == nil {
		cursig, err = parent.Signature()
		if err != nil {
			// This should not happen: parent should exist and be readable,
			// since we've already visited it earlier in the build and we
			// avoid looking at failed/tainted parents.
			return false, err
		}
	}
	changed := parent.Changed(cursig, oldsig)
	//log.Verbose("parent %s: oldsig=%v, cursig=%v, changed=%v",
	//	parent, oldsig, cursig, changed)
	return changed, nil
}
示例#4
0
文件: build.go 项目: sbinet/fubsy
func (self *BuildState) recordNode(node dag.Node) error {
	log.Debug(log.BUILD, "recording successful build of %s %s", node.Typename(), node)
	sig, err := node.Signature()
	log.Debug(log.BUILD, "sig=%v, err=%v", sig, err)
	if err != nil {
		return fmt.Errorf("could not compute signature of target %s: %s",
			node, err)
	}

	record := db.NewBuildRecord()
	record.SetTargetSignature(sig)
	for _, parent := range self.graph.ParentNodes(node) {
		sig, err = parent.Signature()
		if err != nil {
			return err
		}
		record.AddParent(parent.Name(), sig)
	}
	err = self.db.WriteNode(node.Name(), record)
	if err != nil {
		return err
	}
	return nil
}
示例#5
0
文件: build.go 项目: sbinet/fubsy
// 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
}