2016-06-20 10:59:36 +02:00
package main
import (
"io/ioutil"
"os"
2016-06-28 09:19:17 +02:00
"path/filepath"
2016-06-20 10:59:36 +02:00
"runtime"
"strings"
"github.com/kataras/cli"
2016-09-01 05:34:55 +02:00
"github.com/kataras/go-fs"
2016-06-20 10:59:36 +02:00
"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 (
2016-09-01 05:34:55 +02:00
packagesInstallDir = utils . AssetsDirectory + fs . PathSeparator + "iris-command-assets" + fs . PathSeparator
2016-06-30 05:43:29 +02:00
// packages should install with go get before create the package
packagesDependencies = [ ] string { "github.com/iris-contrib/middleware/logger" }
2016-06-20 10:59:36 +02:00
)
2016-06-28 09:19:17 +02:00
func isValidInstallDir ( targetDir string ) bool {
// https://github.com/kataras/iris/issues/237
gopath := os . Getenv ( "GOPATH" )
// remove the last ;/: for any case before the split
if idxLSep := strings . IndexByte ( gopath , os . PathListSeparator ) ; idxLSep == len ( gopath ) - 1 {
gopath = gopath [ 0 : len ( gopath ) - 2 ]
}
2016-06-20 10:59:36 +02:00
2016-06-28 09:19:17 +02:00
// check if we have more than one gopath
gopaths := strings . Split ( gopath , string ( os . PathListSeparator ) )
// the package MUST be installed only inside a valid gopath, if not then print an error to the user.
for _ , gpath := range gopaths {
2016-09-01 05:34:55 +02:00
if strings . HasPrefix ( targetDir , gpath + fs . PathSeparator ) {
2016-06-28 09:19:17 +02:00
return true
}
2016-06-20 10:59:36 +02:00
}
2016-06-28 09:19:17 +02:00
return false
}
2016-06-20 10:59:36 +02:00
2016-06-28 09:19:17 +02:00
func create ( flags cli . Flags ) ( err error ) {
2016-06-20 10:59:36 +02:00
2016-06-28 09:19:17 +02:00
targetDir , err := filepath . Abs ( flags . String ( "dir" ) )
if err != nil {
panic ( err )
2016-06-20 10:59:36 +02:00
}
2016-06-28 09:19:17 +02:00
if ! isValidInstallDir ( targetDir ) {
printer . Dangerf ( "\nPlease make sure you are targeting a directory inside $GOPATH, type iris -h for help." )
return
}
2016-09-01 05:34:55 +02:00
if ! fs . DirectoryExists ( packagesInstallDir ) || ! flags . Bool ( "offline" ) {
2016-06-30 05:43:29 +02:00
// install/update go dependencies at the same time downloading the zip from the github iris-contrib assets
finish := make ( chan bool )
go func ( ) {
go func ( ) {
for _ , source := range packagesDependencies {
gogetCmd := utils . CommandBuilder ( "go" , "get" , source )
if msg , err := gogetCmd . CombinedOutput ( ) ; err != nil {
panic ( "Unable to go get " + source + " please make sure you're connected to the internet.\nSolution: Remove your $GOPATH/src/github.com/iris-contrib/middleware folder and re-run the iris create\nReason:\n" + string ( msg ) )
}
}
finish <- true
} ( )
downloadPackages ( )
<- finish
} ( )
<- finish
close ( finish )
2016-06-20 10:59:36 +02:00
}
createPackage ( flags . String ( "type" ) , targetDir )
return
}
func downloadPackages ( ) {
errMsg := "\nProblem while downloading the assets from the internet for the first time. Trace: %s"
2016-09-02 05:05:44 +02:00
installedDir , err := fs . Install ( PackagesURL , packagesInstallDir , true )
2016-06-20 10:59:36 +02:00
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.
2016-09-01 05:34:55 +02:00
err = fs . CopyDir ( installedDir , packagesInstallDir )
2016-06-20 10:59:36 +02:00
if err != nil {
printer . Dangerf ( errMsg , err . Error ( ) )
return
}
// we don't exit on errors here.
// try to remove the unzipped folder
2016-09-01 05:34:55 +02:00
fs . RemoveFile ( installedDir [ 0 : len ( installedDir ) - 1 ] )
2016-06-20 10:59:36 +02:00
}
func createPackage ( packageName string , targetDir string ) error {
2016-09-01 05:34:55 +02:00
installTo := targetDir // os.Getenv("GOPATH") + fs.PathSeparator + "src" + fs.PathSeparator + targetDir
2016-06-20 10:59:36 +02:00
2016-09-01 05:34:55 +02:00
packageDir := packagesInstallDir + fs . PathSeparator + packageName
err := fs . CopyDir ( packageDir , installTo )
2016-06-20 10:59:36 +02:00
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
2016-09-01 05:34:55 +02:00
mainFile := installTo + fs . PathSeparator + "backend" + fs . PathSeparator + "main.go"
2016-06-20 10:59:36 +02:00
input , err := ioutil . ReadFile ( mainFile )
if err != nil {
printer . Warningf ( "Error while preparing main file: %#v" , err )
}
2016-06-28 09:19:17 +02:00
output := strings . Replace ( string ( input ) , "github.com/iris-contrib/iris-command-assets/" + packageName + "/" , filepath . Base ( targetDir ) + "/" , - 1 )
2016-06-20 10:59:36 +02:00
2016-06-28 09:19:17 +02:00
err = ioutil . WriteFile ( mainFile , [ ] byte ( output ) , 0777 )
2016-06-20 10:59:36 +02:00
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 ] != '/' {
2016-09-01 05:34:55 +02:00
installTo += fs . PathSeparator
2016-06-20 10:59:36 +02:00
}
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"
}
2016-09-01 05:34:55 +02:00
runCmd := utils . CommandBuilder ( "." + fs . PathSeparator + executable )
2016-06-20 10:59:36 +02:00
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
}