func switchBuild(cmd *c.Command, args []string) {
	dev.MustFindCrowbar()
	if ok, _ := dev.IsClean(); !ok {
		log.Fatalln("Crowbar is not clean, cannot switch builds.")
	}
	rels := dev.Releases()
	current := dev.CurrentBuild()
	var target dev.Build
	found := false
	switch len(args) {
	case 0:
		target, found = current, true
	case 1:
		// Were we passed a known release?
		rel, foundRel := rels[args[0]]
		if foundRel {
			for _, build := range []string{current.Name(), "master"} {
				target, found = rel.Builds()[build]
				if found {
					break
				}
			}
		} else {
			target, found = dev.Builds()[args[0]]
		}
	default:
		log.Fatalf("switch takes 0 or 1 argument.")
	}
	if !found {
		log.Fatalf("%s is not anything we can switch to!")
	}
	ok, tokens := dev.Switch(target)
	for _, tok := range tokens {
		if tok.Results != nil {
			log.Printf("%s: %v\n", tok.Name, tok.Results)
		}
	}
	if ok {
		log.Printf("Switched to %s\n", target.FullName())
		os.Exit(0)
	}
	log.Printf("Failed to switch to %s!\n", target.FullName())
	ok, _ = dev.Switch(current)
	os.Exit(1)
}
func isClean(cmd *c.Command, args []string) {
	dev.MustFindCrowbar()
	ok, items := dev.IsClean()
	if ok {
		log.Println("All Crowbar repositories are clean.")
		os.Exit(0)
	}
	for _, item := range items {
		if !item.OK {
			log.Printf("%s is not clean:\n", item.Name)
			for _, line := range item.Results.(git.StatLines) {
				log.Printf("\t%s\n", line.Print())
			}
		}
	}
	os.Exit(1)
	return
}
func sync(cmd *c.Command, args []string) {
	dev.MustFindCrowbar()
	ok, _ := dev.IsClean()
	if !ok {
		log.Printf("Cannot rebase local changes, Crowbar is not clean.\n")
		isClean(cmd, args)
	}
	ok, res := dev.Rebase()
	if ok {
		log.Println("All local changes rebased against upstream.")
		os.Exit(0)
	}
	for _, tok := range res {
		log.Printf("%v: %v %v\n", tok.Name, tok.OK, tok.Results)
	}
	log.Println("Errors rebasing local changes.  All changes unwound.")
	os.Exit(1)
}