blob: f8eb76e1155310579c6566b6fd13fe9f5e272588 [file] [log] [blame]
/*
Copyright 2015 Runtime Inc.
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 main
import (
"fmt"
"github.com/mynewt/newt/cli"
"github.com/spf13/cobra"
"log"
"os"
"path/filepath"
"strings"
)
var ExitOnFailure bool = false
var ExportAll bool = false
var ImportAll bool = false
var NewtVersion string = "1.0"
var NewtRepo *cli.Repo
var NewtLogLevel string = ""
var NewtNest *cli.Nest
func NewtUsage(cmd *cobra.Command, err error) {
if err != nil {
sErr := err.(*cli.NewtError)
log.Printf("[DEBUG] %s", sErr.StackTrace)
fmt.Println("Error: ", sErr.Text)
}
if cmd != nil {
cmd.Usage()
}
os.Exit(1)
}
func targetSetCmd(cmd *cobra.Command, args []string) {
if len(args) != 2 {
NewtUsage(cmd,
cli.NewNewtError("Must specify two arguments (sect & k=v) to set"))
}
t, err := cli.LoadTarget(NewtRepo, args[0])
if err != nil {
NewtUsage(cmd, err)
}
ar := strings.Split(args[1], "=")
t.Vars[ar[0]] = ar[1]
if err := t.Save(); err != nil {
NewtUsage(cmd, err)
}
fmt.Printf("Target %s successfully set %s to %s\n", args[0],
ar[0], ar[1])
}
func targetUnsetCmd(cmd *cobra.Command, args []string) {
if len(args) != 2 {
NewtUsage(cmd,
cli.NewNewtError("Must specify two arguments (sect & k) to unset"))
}
t, err := cli.LoadTarget(NewtRepo, args[0])
if err != nil {
NewtUsage(cmd, err)
}
if err := t.DeleteVar(args[1]); err != nil {
NewtUsage(cmd, err)
}
fmt.Printf("Target %s successfully unset %s\n", args[0], args[1])
}
func targetShowCmd(cmd *cobra.Command, args []string) {
dispSect := ""
if len(args) == 1 {
dispSect = args[0]
}
targets, err := cli.GetTargets(NewtRepo)
if err != nil {
NewtUsage(cmd, err)
}
for _, target := range targets {
if dispSect == "" || dispSect == target.Vars["name"] {
fmt.Println(target.Vars["name"])
vars := target.GetVars()
for k, v := range vars {
fmt.Printf(" %s: %s\n", k, v)
}
}
}
}
func targetCreateCmd(cmd *cobra.Command, args []string) {
if len(args) != 1 {
NewtUsage(cmd, cli.NewNewtError("Wrong number of args to create cmd."))
}
fmt.Println("Creating target " + args[0])
if cli.TargetExists(NewtRepo, args[0]) {
NewtUsage(cmd, cli.NewNewtError(
"Target already exists, cannot create target with same name."))
}
target := &cli.Target{
Repo: NewtRepo,
Vars: map[string]string{},
}
target.Vars["name"] = args[0]
err := target.Save()
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Target %s sucessfully created!\n", args[0])
}
}
func targetBuildCmd(cmd *cobra.Command, args []string) {
if len(args) < 1 {
NewtUsage(cmd, cli.NewNewtError("Must specify target to build"))
}
t, err := cli.LoadTarget(NewtRepo, args[0])
if err != nil {
NewtUsage(cmd, err)
}
if len(args) > 1 && args[1] == "clean" {
if len(args) > 2 && args[2] == "all" {
err = t.BuildClean(true)
} else {
err = t.BuildClean(false)
}
} else {
err = t.Build()
}
if err != nil {
NewtUsage(cmd, err)
} else {
fmt.Println("Successfully run!")
}
}
func targetDelCmd(cmd *cobra.Command, args []string) {
if len(args) < 1 {
NewtUsage(cmd, cli.NewNewtError("Must specify target to delete"))
}
t, err := cli.LoadTarget(NewtRepo, args[0])
if err != nil {
NewtUsage(cmd, err)
}
if err := t.Remove(); err != nil {
NewtUsage(cmd, err)
}
fmt.Printf("Target %s successfully removed\n", args[0])
}
func targetTestCmd(cmd *cobra.Command, args []string) {
if len(args) < 1 {
NewtUsage(cmd, cli.NewNewtError("Must specify target to build"))
}
t, err := cli.LoadTarget(NewtRepo, args[0])
if err != nil {
NewtUsage(cmd, err)
}
if len(args) > 1 && args[1] == "clean" {
if len(args) > 2 && args[2] == "all" {
err = t.Test("testclean", true)
} else {
err = t.Test("testclean", false)
}
} else {
err = t.Test("test", ExitOnFailure)
}
if err != nil {
NewtUsage(cmd, err)
} else {
fmt.Println("Successfully run!")
}
}
func targetExportCmd(cmd *cobra.Command, args []string) {
var targetName string
if ExportAll {
targetName = ""
} else {
if len(args) < 1 {
NewtUsage(cmd, cli.NewNewtError("Must either specify -a flag or name of "+
"target to export"))
}
targetName = args[0]
}
err := cli.ExportTargets(NewtRepo, targetName, ExportAll, os.Stdout)
if err != nil {
NewtUsage(cmd, err)
}
}
func targetImportCmd(cmd *cobra.Command, args []string) {
var targetName string
if ImportAll {
targetName = ""
} else {
if len(args) < 1 {
NewtUsage(cmd, cli.NewNewtError("Must either specify -a flag or name of "+
"target to import"))
}
targetName = args[0]
}
err := cli.ImportTargets(NewtRepo, targetName, ImportAll, os.Stdin)
if err != nil {
NewtUsage(cmd, err)
}
fmt.Println("Target(s) successfully imported!")
}
func targetAddCmds(base *cobra.Command) {
targetCmd := &cobra.Command{
Use: "target",
Short: "Set and view target information",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
cli.Init(NewtLogLevel)
var err error
NewtRepo, err = cli.NewRepo()
if err != nil {
NewtUsage(nil, err)
}
},
Run: func(cmd *cobra.Command, args []string) {
cmd.Usage()
},
}
setCmd := &cobra.Command{
Use: "set",
Short: "Set target configuration variable",
Run: targetSetCmd,
}
targetCmd.AddCommand(setCmd)
unsetCmd := &cobra.Command{
Use: "unset",
Short: "Unset target configuration variable",
Run: targetUnsetCmd,
}
targetCmd.AddCommand(unsetCmd)
delCmd := &cobra.Command{
Use: "delete",
Short: "Delete target",
Run: targetDelCmd,
}
targetCmd.AddCommand(delCmd)
createCmd := &cobra.Command{
Use: "create",
Short: "Create a target",
Run: targetCreateCmd,
}
targetCmd.AddCommand(createCmd)
showCmd := &cobra.Command{
Use: "show",
Short: "View target configuration variables",
Run: targetShowCmd,
}
targetCmd.AddCommand(showCmd)
buildCmd := &cobra.Command{
Use: "build",
Short: "Build target",
Run: targetBuildCmd,
}
targetCmd.AddCommand(buildCmd)
testCmd := &cobra.Command{
Use: "test",
Short: "Test target",
Run: targetTestCmd,
}
targetCmd.AddCommand(testCmd)
exportCmd := &cobra.Command{
Use: "export",
Short: "Export target",
Run: targetExportCmd,
}
exportCmd.PersistentFlags().BoolVarP(&ExportAll, "export-all", "a", false,
"If present, export all targets")
targetCmd.AddCommand(exportCmd)
importCmd := &cobra.Command{
Use: "import",
Short: "Import target",
Run: targetImportCmd,
}
importCmd.PersistentFlags().BoolVarP(&ImportAll, "import-all", "a", false,
"If present, import all targets")
targetCmd.AddCommand(importCmd)
base.AddCommand(targetCmd)
}
func repoCreateCmd(cmd *cobra.Command, args []string) {
// must specify a repo name to create
if len(args) != 1 {
NewtUsage(cmd, cli.NewNewtError("Must specify a repo name to repo create"))
}
cwd, err := os.Getwd()
if err != nil {
NewtUsage(cmd, err)
}
_, err = cli.CreateRepo(cwd, args[0])
if err != nil {
NewtUsage(cmd, err)
}
fmt.Println("Repo " + args[0] + " successfully created!")
}
func repoAddCmds(baseCmd *cobra.Command) {
repoCmd := &cobra.Command{
Use: "repo",
Short: "Commands to manipulate the base repository",
Run: func(cmd *cobra.Command, args []string) {
cmd.Usage()
},
}
createCmd := &cobra.Command{
Use: "create",
Short: "Create a repository",
Run: repoCreateCmd,
}
repoCmd.AddCommand(createCmd)
baseCmd.AddCommand(repoCmd)
}
func dispEgg(egg *cli.Egg) error {
fmt.Printf("Egg %s, version %s\n", egg.FullName, egg.Version)
fmt.Printf(" path: %s\n", filepath.Clean(egg.BasePath))
if egg.Capabilities != nil {
fmt.Printf(" capabilities: ")
caps, err := egg.GetCapabilities()
if err != nil {
return err
}
for _, capability := range caps {
fmt.Printf("%s ", capability)
}
fmt.Printf("\n")
}
if len(egg.Deps) > 0 {
fmt.Printf(" deps: ")
for _, dep := range egg.Deps {
if dep == nil {
continue
}
fmt.Printf("%s ", dep)
}
fmt.Printf("\n")
}
if egg.LinkerScript != "" {
fmt.Printf(" linkerscript: %s\n", egg.LinkerScript)
}
return nil
}
func eggListCmd(cmd *cobra.Command, args []string) {
eggMgr, err := cli.NewEggMgr(NewtRepo, nil)
if err != nil {
NewtUsage(cmd, err)
}
for _, egg := range eggMgr.Eggs {
if err := dispEgg(egg); err != nil {
NewtUsage(cmd, err)
}
}
}
func eggCheckDepsCmd(cmd *cobra.Command, args []string) {
eggMgr, err := cli.NewEggMgr(NewtRepo, nil)
if err != nil {
NewtUsage(cmd, err)
}
if err := eggMgr.CheckDeps(); err != nil {
NewtUsage(cmd, err)
}
fmt.Println("Dependencies successfully resolved!")
}
func eggAddCmds(baseCmd *cobra.Command) {
eggCmd := &cobra.Command{
Use: "egg",
Short: "Commands to list and inspect eggs on a repo",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
cli.Init(NewtLogLevel)
var err error
NewtRepo, err = cli.NewRepo()
if err != nil {
NewtUsage(nil, err)
}
},
Run: func(cmd *cobra.Command, args []string) {
NewtUsage(cmd, nil)
},
}
listCmd := &cobra.Command{
Use: "list",
Short: "List eggs in the current repository",
Run: eggListCmd,
}
eggCmd.AddCommand(listCmd)
checkDepsCmd := &cobra.Command{
Use: "checkdeps",
Short: "Check egg dependencies",
Run: eggCheckDepsCmd,
}
eggCmd.AddCommand(checkDepsCmd)
baseCmd.AddCommand(eggCmd)
}
func nestLayCmd(cmd *cobra.Command, args []string) {
if len(args) != 2 {
NewtUsage(cmd,
cli.NewNewtError("Must specify name and URL to lay clutch file"))
}
clutchName := args[0]
clutchUrl := args[1]
clutch, err := cli.NewClutch(NewtNest)
if err != nil {
NewtUsage(cmd, err)
}
clutch.Name = clutchName
clutch.RemoteUrl = clutchUrl
eggMgr, err := cli.NewEggMgr(NewtRepo, nil)
if err != nil {
NewtUsage(cmd, err)
}
if err := clutch.LoadFromPM(eggMgr); err != nil {
NewtUsage(cmd, err)
}
clutchStr, err := clutch.Serialize()
if err != nil {
NewtUsage(cmd, err)
}
fmt.Print(clutchStr)
}
func nestGetCmd(cmd *cobra.Command, args []string) {
if len(args) != 2 {
NewtUsage(cmd,
cli.NewNewtError("Must specify both name and URL to larva install command"))
}
name := args[0]
url := args[1]
clutch, err := cli.NewClutch(NewtNest)
if err != nil {
NewtUsage(cmd, err)
}
if err := clutch.Install(name, url); err != nil {
NewtUsage(cmd, err)
}
fmt.Println("Clutch " + name + " sucessfully installed to Nest.")
}
func nestShowCmd(cmd *cobra.Command, args []string) {
clutches, err := NewtNest.GetClutches()
if err != nil {
NewtUsage(cmd, err)
}
for name, clutch := range clutches {
fmt.Printf("Remote clutch %s (eggshells: %d)\n", name, len(clutch.EggShells))
}
}
func nestAddCmds(baseCmd *cobra.Command) {
nestCmd := &cobra.Command{
Use: "nest",
Short: "Commands to manage nests & clutches (remote egg repositories)",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
cli.Init(NewtLogLevel)
var err error
NewtRepo, err = cli.NewRepo()
if err != nil {
NewtUsage(nil, err)
}
NewtNest, err = cli.NewNest(NewtRepo)
if err != nil {
NewtUsage(nil, err)
}
},
Run: func(cmd *cobra.Command, args []string) {
NewtUsage(cmd, nil)
},
}
layCmd := &cobra.Command{
Use: "lay",
Short: "Lay (generate) a clutch file from the eggs in the current directory",
Run: nestLayCmd,
}
nestCmd.AddCommand(layCmd)
getCmd := &cobra.Command{
Use: "get",
Short: "Get a remote clutch, and put it in the current nest",
Run: nestGetCmd,
}
nestCmd.AddCommand(getCmd)
showCmd := &cobra.Command{
Use: "show",
Short: "Show the clutches installed in the current nest",
Run: nestShowCmd,
}
nestCmd.AddCommand(showCmd)
baseCmd.AddCommand(nestCmd)
}
func parseCmds() *cobra.Command {
newtCmd := &cobra.Command{
Use: "newt",
Short: "Newt is a tool to help you compose and build your own OS",
Long: `Newt allows you to create your own embedded project based on the
Newt operating system`,
Run: func(cmd *cobra.Command, args []string) {
cmd.Usage()
},
}
newtCmd.PersistentFlags().StringVarP(&NewtLogLevel, "loglevel", "l",
"WARN", "Log level, defaults to WARN.")
versCmd := &cobra.Command{
Use: "version",
Short: "Print the Newt version number",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Newt version: ", NewtVersion)
},
}
newtCmd.AddCommand(versCmd)
targetAddCmds(newtCmd)
repoAddCmds(newtCmd)
eggAddCmds(newtCmd)
nestAddCmds(newtCmd)
return newtCmd
}
func main() {
cmd := parseCmds()
cmd.Execute()
}