1
0
mirror of https://github.com/kataras/iris.git synced 2026-01-18 01:15:59 +00:00

Update to rc.2 | NEW: iris run main.go https://github.com/kataras/iris/issues/192

Not tested on linux yet,(I do not have a linux station now). Post an
issue if iris run main.go doesnt works as expected
This commit is contained in:
Makis Maropoulos
2016-06-20 11:59:36 +03:00
parent 39e1504ba3
commit e9a4746000
10 changed files with 336 additions and 175 deletions

View File

@@ -7,14 +7,14 @@ This package is the command line tool for [../](https://github.com/kataras/iris
[![Iris installed screen](https://raw.githubusercontent.com/iris-contrib/website/gh-pages/assets/iris_cli_screen2.png)](https://raw.githubusercontent.com/iris-contrib/website/gh-pages/assets/iris_cli_screen2.png)
## Install
Current version: 0.0.4
Current version: 0.0.5
```sh
go get -u github.com/kataras/iris/iris
```
## Usage
# Usage
```sh
@@ -24,7 +24,7 @@ $ iris [command] [-flags]
> Note that you must have $GOPATH/bin to your $PATH system/environment variable.
## Create
## create
**The create command** creates for you a start project in a directory
@@ -57,15 +57,24 @@ iris create -d myproject
Will create the basic sample package to the `$GOPATH/src/myproject` folder and run the app.
## run
## Version
**The run command** runs & reload on file changes your Iris station
It's like ` go run ` but with directory watcher and re-run on .go file changes.
```sh
iris run main.go
```
[![Iris CLI run showcase](https://raw.githubusercontent.com/iris-contrib/website/gh-pages/assets/iris_command_line_tool_run_command.png)](https://raw.githubusercontent.com/iris-contrib/website/gh-pages/assets/iris_command_line_tool_run_command.png)
## version
```sh
iris version
```
Will print the current iris' installed version to your machine
## TODO
- [ ] Add more templates
Will print the current Iris' installed version to your machine

131
iris/create.go Normal file
View File

@@ -0,0 +1,131 @@
package main
import (
"io/ioutil"
"os"
"runtime"
"strings"
"github.com/kataras/cli"
"github.com/kataras/iris/utils"
)
const (
// PackagesURL the url to download all the packages
PackagesURL = "https://github.com/iris-contrib/iris-command-assets/archive/master.zip"
// PackagesExportedName the folder created after unzip
PackagesExportedName = "iris-command-assets-master"
)
var (
packagesInstallDir = utils.AssetsDirectory + utils.PathSeparator + "iris-command-assets" + utils.PathSeparator
)
func create(flags cli.Flags) (err error) {
if !utils.DirectoryExists(packagesInstallDir) || !flags.Bool("offline") {
downloadPackages()
}
targetDir := flags.String("dir")
// remove first and last / if any
if strings.HasPrefix(targetDir, "./") || strings.HasPrefix(targetDir, "."+utils.PathSeparator) {
targetDir = targetDir[2:]
}
if targetDir[len(targetDir)-1] == '/' {
targetDir = targetDir[0 : len(targetDir)-1]
}
//
createPackage(flags.String("type"), targetDir)
return
}
func downloadPackages() {
errMsg := "\nProblem while downloading the assets from the internet for the first time. Trace: %s"
installedDir, err := utils.Install(PackagesURL, packagesInstallDir)
if err != nil {
printer.Dangerf(errMsg, err.Error())
return
}
// installedDir is the packagesInstallDir+PackagesExportedName, we will copy these contents to the parent, to the packagesInstallDir, because of import paths.
err = utils.CopyDir(installedDir, packagesInstallDir)
if err != nil {
printer.Dangerf(errMsg, err.Error())
return
}
// we don't exit on errors here.
// try to remove the unzipped folder
utils.RemoveFile(installedDir[0 : len(installedDir)-1])
}
func createPackage(packageName string, targetDir string) error {
installTo := os.Getenv("GOPATH") + utils.PathSeparator + "src" + utils.PathSeparator + targetDir
packageDir := packagesInstallDir + utils.PathSeparator + packageName
err := utils.CopyDir(packageDir, installTo)
if err != nil {
printer.Dangerf("\nProblem while copying the %s package to the %s. Trace: %s", packageName, installTo, err.Error())
return err
}
// now replace main.go's 'github.com/iris-contrib/iris-command-assets/basic/' with targetDir
// hardcode all that, we don't have anything special and neither will do
targetDir = strings.Replace(targetDir, "\\", "/", -1) // for any case
mainFile := installTo + utils.PathSeparator + "backend" + utils.PathSeparator + "main.go"
input, err := ioutil.ReadFile(mainFile)
if err != nil {
printer.Warningf("Error while preparing main file: %#v", err)
}
output := strings.Replace(string(input), "github.com/iris-contrib/iris-command-assets/"+packageName+"/", targetDir+"/", -1)
err = ioutil.WriteFile(mainFile, []byte(output), 0644)
if err != nil {
printer.Warningf("Error while preparing main file: %#v", err)
}
printer.Infof("%s package was installed successfully [%s]", packageName, installTo)
// build & run the server
// go build
buildCmd := utils.CommandBuilder("go", "build")
if installTo[len(installTo)-1] != os.PathSeparator || installTo[len(installTo)-1] != '/' {
installTo += utils.PathSeparator
}
buildCmd.Dir = installTo + "backend"
buildCmd.Stderr = os.Stderr
err = buildCmd.Start()
if err != nil {
printer.Warningf("\n Failed to build the %s package. Trace: %s", packageName, err.Error())
}
buildCmd.Wait()
print("\n\n")
// run backend/backend(.exe)
executable := "backend"
if runtime.GOOS == "windows" {
executable += ".exe"
}
runCmd := utils.CommandBuilder("." + utils.PathSeparator + executable)
runCmd.Dir = buildCmd.Dir
runCmd.Stdout = os.Stdout
runCmd.Stderr = os.Stderr
err = runCmd.Start()
if err != nil {
printer.Warningf("\n Failed to run the %s package. Trace: %s", packageName, err.Error())
}
runCmd.Wait()
return err
}

View File

@@ -5,8 +5,14 @@ package main
go get -u github.com/kataras/iris/iris
// create command
create an empty folder, open the command prompt/terminal there, type and press enter:
iris create
// run command
navigate to your app's directory and execute:
iris run main.go
*/

View File

@@ -3,155 +3,61 @@ package main
import (
"os"
_ "syscall"
"strings"
"io/ioutil"
"runtime"
"github.com/fatih/color"
"github.com/kataras/cli"
"github.com/kataras/iris"
"github.com/kataras/iris/utils"
)
const (
// PackagesURL the url to download all the packages
PackagesURL = "https://github.com/iris-contrib/iris-command-assets/archive/master.zip"
// PackagesExportedName the folder created after unzip
PackagesExportedName = "iris-command-assets-master"
"github.com/kataras/iris/config"
"github.com/kataras/iris/logger"
)
var (
app *cli.App
// SuccessPrint prints with a green color
SuccessPrint = color.New(color.FgGreen).Add(color.Bold).PrintfFunc()
// InfoPrint prints with the cyan color
InfoPrint = color.New(color.FgHiCyan).Add(color.Bold).PrintfFunc()
packagesInstallDir = os.Getenv("GOPATH") + utils.PathSeparator + "src" + utils.PathSeparator + "github.com" + utils.PathSeparator + "iris-contrib" + utils.PathSeparator + "iris-command-assets" + utils.PathSeparator
app *cli.App
printer *logger.Logger
workingDir string
)
func init() {
app = cli.NewApp("iris", "Command line tool for Iris web framework", "0.0.4")
// set the current working dir
if d, err := os.Getwd(); err != nil {
panic(err)
} else {
workingDir = d
}
// defaultInstallDir is the default directory which the create will copy and run the package when finish downloading
// it's just the last path part of the workingDir
defaultInstallDir := workingDir[strings.LastIndexByte(workingDir, os.PathSeparator)+1:]
// init the cli app
app = cli.NewApp("iris", "Command line tool for Iris web framework", "0.0.5")
// version command
app.Command(cli.Command("version", "\t prints your iris version").Action(func(cli.Flags) error { app.Printf("%s", iris.Version); return nil }))
// create command/-/create.go
createCmd := cli.Command("create", "create a project to a given directory").
Flag("offline", false, "set to true to disable the packages download on each create command").
Flag("dir", "myiris", "$GOPATH/src/$dir the directory to install the sample package").
Flag("dir", defaultInstallDir, "$GOPATH/src/$dir the directory to install the sample package").
Flag("type", "basic", "creates a project based on the -t package. Currently, available types are 'basic' & 'static'").
Action(create)
// run command/-/run.go
runAndWatchCmd := cli.Command("run", "runs and reload on source code changes, example: iris run main.go").Action(runAndWatch)
// register the commands
app.Command(createCmd)
app.Command(runAndWatchCmd)
// init the logger
printer = logger.New(config.DefaultLogger())
}
func main() {
app.Run(func(cli.Flags) error { return nil })
}
func create(flags cli.Flags) (err error) {
if !utils.DirectoryExists(packagesInstallDir) || !flags.Bool("offline") {
downloadPackages()
}
targetDir := flags.String("dir")
// remove first and last / if any
if strings.HasPrefix(targetDir, "./") || strings.HasPrefix(targetDir, "."+utils.PathSeparator) {
targetDir = targetDir[2:]
}
if targetDir[len(targetDir)-1] == '/' {
targetDir = targetDir[0 : len(targetDir)-1]
}
//
createPackage(flags.String("type"), targetDir)
return
}
func downloadPackages() {
errMsg := "\nProblem while downloading the assets from the internet for the first time. Trace: %s"
installedDir, err := utils.Install(PackagesURL, packagesInstallDir)
if err != nil {
app.Printf(errMsg, err.Error())
return
}
// installedDir is the packagesInstallDir+PackagesExportedName, we will copy these contents to the parent, to the packagesInstallDir, because of import paths.
err = utils.CopyDir(installedDir, packagesInstallDir)
if err != nil {
app.Printf(errMsg, err.Error())
return
}
// we don't exit on errors here.
// try to remove the unzipped folder
utils.RemoveFile(installedDir[0 : len(installedDir)-1])
}
func createPackage(packageName string, targetDir string) error {
installTo := os.Getenv("GOPATH") + utils.PathSeparator + "src" + utils.PathSeparator + targetDir
packageDir := packagesInstallDir + utils.PathSeparator + packageName
err := utils.CopyDir(packageDir, installTo)
if err != nil {
app.Printf("\nProblem while copying the %s package to the %s. Trace: %s", packageName, installTo, err.Error())
return err
}
// now replace main.go's 'github.com/iris-contrib/iris-command-assets/basic/' with targetDir
// hardcode all that, we don't have anything special and neither will do
targetDir = strings.Replace(targetDir, "\\", "/", -1) // for any case
mainFile := installTo + utils.PathSeparator + "backend" + utils.PathSeparator + "main.go"
input, err := ioutil.ReadFile(mainFile)
if err != nil {
app.Printf("Error while preparing main file: %#v", err)
}
output := strings.Replace(string(input), "github.com/iris-contrib/iris-command-assets/"+packageName+"/", targetDir+"/", -1)
err = ioutil.WriteFile(mainFile, []byte(output), 0644)
if err != nil {
app.Printf("Error while preparing main file: %#v", err)
}
InfoPrint("%s package was installed successfully", packageName)
// build & run the server
// go build
buildCmd := utils.CommandBuilder("go", "build")
if installTo[len(installTo)-1] != os.PathSeparator || installTo[len(installTo)-1] != '/' {
installTo += utils.PathSeparator
}
buildCmd.Dir = installTo + "backend"
buildCmd.Stderr = os.Stderr
err = buildCmd.Start()
if err != nil {
app.Printf("\n Failed to build the %s package. Trace: %s", packageName, err.Error())
}
buildCmd.Wait()
print("\n\n")
// run backend/backend(.exe)
executable := "backend"
if runtime.GOOS == "windows" {
executable += ".exe"
}
runCmd := utils.CommandBuilder("." + utils.PathSeparator + executable)
runCmd.Dir = buildCmd.Dir
runCmd.Stdout = os.Stdout
runCmd.Stderr = os.Stderr
err = runCmd.Start()
if err != nil {
app.Printf("\n Failed to run the %s package. Trace: %s", packageName, err.Error())
}
runCmd.Wait()
return err
// run the application
app.Run(func(f cli.Flags) error {
return nil
})
}

96
iris/run.go Normal file
View File

@@ -0,0 +1,96 @@
package main
import (
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync/atomic"
"github.com/kataras/cli"
"github.com/kataras/iris/errors"
"github.com/kataras/iris/utils"
)
var (
errInvalidArgs = errors.New("Invalid arguments [%s], type -h to get assistant")
errInvalidExt = errors.New("%s is not a go program")
errUnexpected = errors.New("Unexpected error!!! Please post an issue here: https://github.com/kataras/iris/issues")
goExt = ".go"
)
func runAndWatch(flags cli.Flags) error {
if len(os.Args) <= 2 {
err := errInvalidArgs.Format(strings.Join(os.Args, ","))
printer.Dangerf(err.Error())
return err
}
programPath := ""
filenameCh := make(chan string)
if len(os.Args) > 2 { // iris run main.go
programPath = os.Args[2]
if programPath[len(programPath)-1] == '/' {
programPath = programPath[0 : len(programPath)-1]
}
if filepath.Ext(programPath) != goExt {
return errInvalidExt.Format(programPath)
}
}
// here(below), we don't return the error because the -help command doesn't help the user for these errors.
// run the file watcher before all, because the user maybe has a go syntax error before the first run
utils.WatchDirectoryChanges(workingDir, func(fname string) {
if filepath.Ext(fname) == goExt {
filenameCh <- fname
}
}, printer)
// we don't use go build and run from the executable, for performance reasons, no need this is a development action already
goRun := utils.CommandBuilder("go", "run", programPath)
goRun.Dir = workingDir
goRun.Stdout = os.Stdout
goRun.Stderr = os.Stderr
if err := goRun.Start(); err != nil {
printer.Dangerf("\n [ERROR] Failed to run the %s iris program. Trace: %s", programPath, err.Error())
return nil
}
isWindows := runtime.GOOS == "windows"
defer func() {
printer.Dangerf("")
printer.Panic(errUnexpected)
}()
var times uint32 = 1
for {
select {
case fname := <-filenameCh:
{
// it's not a warning but I like to use purple color for this message
printer.Warningf("\n/-%d-/ File '%s' changed, re-running...", atomic.LoadUint32(&times), fname)
// force kill, sometimes runCmd.Process.Kill or Signal(os.Kill) doesn't kill the child of the go's go run command ( which is the iris program)
if isWindows {
utils.CommandBuilder("taskkill", "/F", "/T", "/PID", strconv.Itoa(goRun.Process.Pid)).Run()
} else {
utils.CommandBuilder("kill", "-INT", "-"+strconv.Itoa(goRun.Process.Pid)).Run()
}
goRun = utils.CommandBuilder("go", "run", programPath)
goRun.Dir = workingDir
goRun.Stderr = os.Stderr
if err := goRun.Start(); err != nil {
printer.Warningf("\n [ERROR ON RELOAD] Failed to run the %s iris program. Trace: %s", programPath, err.Error())
} else {
atomic.AddUint32(&times, 1)
// don't print success on anything here because we may have error on iris itself, no need to print any message we are no spammers.
}
}
}
}
}