Repository: incubator-mynewt-newt Updated Branches: refs/heads/develop 21deb707e -> 6b585caed
add ability to create new packages to newt based on templates Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/6b585cae Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/6b585cae Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/6b585cae Branch: refs/heads/develop Commit: 6b585caed4026f00bc2d646664f55ab0f0129f61 Parents: 21deb70 Author: Sterling Hughes <sterl...@apache.org> Authored: Tue Oct 11 12:16:02 2016 +0200 Committer: Sterling Hughes <sterl...@apache.org> Committed: Tue Oct 11 12:16:02 2016 +0200 ---------------------------------------------------------------------- newt/cli/pkg_cmds.go | 78 +++++++++ newt/newt.go | 1 + newt/project/pkgwriter.go | 174 +++++++++++++++++++ newt/vendor/mynewt.apache.org/newt/util/util.go | 12 ++ util/util.go | 12 ++ 5 files changed, 277 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6b585cae/newt/cli/pkg_cmds.go ---------------------------------------------------------------------- diff --git a/newt/cli/pkg_cmds.go b/newt/cli/pkg_cmds.go new file mode 100644 index 0000000..0972957 --- /dev/null +++ b/newt/cli/pkg_cmds.go @@ -0,0 +1,78 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 cli + +import ( + "strings" + + "github.com/spf13/cobra" + "mynewt.apache.org/newt/newt/project" +) + +var NewTypeStr = "pkg" + +func pkgNewCmd(cmd *cobra.Command, args []string) { + NewTypeStr = strings.ToUpper(NewTypeStr) + + pw := project.NewPackageWriter() + if err := pw.ConfigurePackage(NewTypeStr, args[0]); err != nil { + NewtUsage(cmd, err) + } + if err := pw.WritePackage(); err != nil { + NewtUsage(cmd, err) + } +} + +func AddPackageCommands(cmd *cobra.Command) { + /* Add the base package command, on top of which other commands are + * keyed + */ + pkgHelpText := "Commands for creating and manipulating packages" + pkgHelpEx := "newt pkg new --type=pkg libs/mylib" + + pkgCmd := &cobra.Command{ + Use: "pkg", + Short: "Create and manage packages in the current workspace", + Long: pkgHelpText, + Example: pkgHelpEx, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, + } + + cmd.AddCommand(pkgCmd) + + /* Package new command, create a new package */ + newCmdHelpText := "" + newCmdHelpEx := "" + + newCmd := &cobra.Command{ + Use: "new", + Short: "Create a new package, from a template", + Long: newCmdHelpText, + Example: newCmdHelpEx, + Run: pkgNewCmd, + } + + newCmd.PersistentFlags().StringVarP(&NewTypeStr, "type", "t", + "pkg", "Type of package to create: pkg, bsp, sdk. Default pkg.") + + pkgCmd.AddCommand(newCmd) +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6b585cae/newt/newt.go ---------------------------------------------------------------------- diff --git a/newt/newt.go b/newt/newt.go index 79dc9a4..733e28f 100644 --- a/newt/newt.go +++ b/newt/newt.go @@ -127,6 +127,7 @@ func main() { cli.AddImageCommands(cmd) cli.AddRunCommands(cmd) cli.AddValsCommands(cmd) + cli.AddPackageCommands(cmd) /* only pass the first two args to check for complete command */ if len(os.Args) > 2 { http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6b585cae/newt/project/pkgwriter.go ---------------------------------------------------------------------- diff --git a/newt/project/pkgwriter.go b/newt/project/pkgwriter.go new file mode 100644 index 0000000..6e39245 --- /dev/null +++ b/newt/project/pkgwriter.go @@ -0,0 +1,174 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 project + +import ( + "fmt" + "io/ioutil" + "os" + "path" + "regexp" + "strings" + + "mynewt.apache.org/newt/newt/downloader" + "mynewt.apache.org/newt/util" +) + +type PackageWriter struct { + downloader *downloader.GithubDownloader + repo string + targetPath string + template string + fullName string + project *Project +} + +var TemplateRepoMap = map[string]string{ + "SDK": "incubator-incubator-mynewt-pkg-sdk", + "BSP": "incubator-incubator-mynewt-pkg-bsp", + "PKG": "incubator-incubator-mynewt-pkg-pkg", +} + +const PACKAGEWRITER_GITHUB_DOWNLOAD_USER = "apache" +const PACKAGEWRITER_GITHUB_DOWNLOAD_BRANCH = "master" + +func (pw *PackageWriter) ConfigurePackage(template string, loc string) error { + str, ok := TemplateRepoMap[template] + if !ok { + return util.NewNewtError(fmt.Sprintf("Cannot find matching "+ + "repository for template %s", template)) + } + pw.repo = str + + pw.fullName = path.Clean(loc) + path := pw.project.Path() + path = path + "/" + pw.fullName + + if util.NodeExist(path) { + return util.NewNewtError(fmt.Sprintf("Cannot place a new package in "+ + "%s, path already exists.", path)) + } + + pw.template = template + pw.targetPath = path + + return nil +} + +func (pw *PackageWriter) cleanupPackageFile(pfile string) error { + f, err := os.Open(pfile) + if err != nil { + return util.ChildNewtError(err) + } + defer f.Close() + + data, _ := ioutil.ReadAll(f) + + // Search & replace file contents + re := regexp.MustCompile("your-pkg-name") + res := re.ReplaceAllString(string(data), pw.fullName) + + if err := ioutil.WriteFile(pfile, []byte(res), 0666); err != nil { + return util.ChildNewtError(err) + } + + return nil +} + +func (pw *PackageWriter) fixupPKG() error { + pkgBase := path.Base(pw.fullName) + + // Move include file to name after package name + if err := util.MoveFile(pw.targetPath+"/include/your-path/your-file.h", + pw.targetPath+"/include/your-path/"+pkgBase+".h"); err != nil { + return err + } + + // Move source file + if err := util.MoveFile(pw.targetPath+"/src/your-source.c", + pw.targetPath+"/src/"+pkgBase+".c"); err != nil { + return err + } + + if err := util.CopyDir(pw.targetPath+"/include/your-path/", + pw.targetPath+"/include/"+pkgBase+"/"); err != nil { + return err + } + + if err := os.RemoveAll(pw.targetPath + "/include/your-path/"); err != nil { + return util.ChildNewtError(err) + } + + if err := pw.cleanupPackageFile(pw.targetPath + "/pkg.yml"); err != nil { + return err + } + + return nil +} + +func (pw *PackageWriter) WritePackage() error { + dl := pw.downloader + + dl.User = PACKAGEWRITER_GITHUB_DOWNLOAD_USER + dl.Repo = pw.repo + + util.StatusMessage(util.VERBOSITY_DEFAULT, + "Download package template for package type %s.\n", + strings.ToLower(pw.template)) + + tmpdir, err := dl.DownloadRepo(PACKAGEWRITER_GITHUB_DOWNLOAD_BRANCH) + if err != nil { + return err + } + + if err := os.RemoveAll(tmpdir + "/.git/"); err != nil { + return util.NewNewtError(err.Error()) + } + + if err := util.CopyDir(tmpdir, pw.targetPath); err != nil { + return err + } + + switch pw.template { + case "PKG": + if err := pw.fixupPKG(); err != nil { + return err + } + } + + util.StatusMessage(util.VERBOSITY_DEFAULT, + "Package successfuly installed into %s.\n", pw.targetPath) + + return nil +} + +/** + * Create new PackageWriter structure, and return it + */ +func NewPackageWriter() *PackageWriter { + proj := GetProject() + + pw := &PackageWriter{ + project: proj, + downloader: downloader.NewGithubDownloader(), + } + + return pw +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6b585cae/newt/vendor/mynewt.apache.org/newt/util/util.go ---------------------------------------------------------------------- diff --git a/newt/vendor/mynewt.apache.org/newt/util/util.go b/newt/vendor/mynewt.apache.org/newt/util/util.go index 3ecf400..4aae5a7 100644 --- a/newt/vendor/mynewt.apache.org/newt/util/util.go +++ b/newt/vendor/mynewt.apache.org/newt/util/util.go @@ -430,6 +430,18 @@ func CopyDir(srcDirStr, dstDirStr string) error { return nil } +func MoveFile(srcFile string, destFile string) error { + if err := CopyFile(srcFile, destFile); err != nil { + return err + } + + if err := os.RemoveAll(srcFile); err != nil { + return err + } + + return nil +} + // Reads each line from the specified text file into an array of strings. If a // line ends with a backslash, it is concatenated with the following line. func ReadLines(path string) ([]string, error) { http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6b585cae/util/util.go ---------------------------------------------------------------------- diff --git a/util/util.go b/util/util.go index 3ecf400..4aae5a7 100644 --- a/util/util.go +++ b/util/util.go @@ -430,6 +430,18 @@ func CopyDir(srcDirStr, dstDirStr string) error { return nil } +func MoveFile(srcFile string, destFile string) error { + if err := CopyFile(srcFile, destFile); err != nil { + return err + } + + if err := os.RemoveAll(srcFile); err != nil { + return err + } + + return nil +} + // Reads each line from the specified text file into an array of strings. If a // line ends with a backslash, it is concatenated with the following line. func ReadLines(path string) ([]string, error) {