github.com/jd-ly/cmd@v1.0.10/revel/run.go (about)

     1  // Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
     2  // Revel Framework source code and usage is governed by a MIT style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"strconv"
     9  	"encoding/json"
    10  	"fmt"
    11  	"github.com/jd-ly/cmd/harness"
    12  	"github.com/jd-ly/cmd/model"
    13  	"github.com/jd-ly/cmd/utils"
    14  	"os"
    15  )
    16  
    17  var cmdRun = &Command{
    18  	UsageLine: "run [-m [run mode] -p [port]] [import path] ",
    19  	Short:     "run a Revel application",
    20  	Long: `
    21  Run the Revel web application named by the given import path.
    22  
    23  For example, to run the chat room sample application:
    24  
    25      revel run -m dev github.com/revel/examples/chat
    26  
    27  The run mode is used to select which set of app.conf configuration should
    28  apply and may be used to determine logic in the application itself.
    29  
    30  Run mode defaults to "dev".
    31  
    32  You can set a port as well.  For example:
    33  
    34      revel run -m prod -p 8080 github.com/revel/examples/chat `,
    35  }
    36  
    37  // RunArgs holds revel run parameters
    38  type RunArgs struct {
    39  	ImportPath string
    40  	Mode       string
    41  	Port       int
    42  }
    43  
    44  func init() {
    45  	cmdRun.RunWith = runApp
    46  	cmdRun.UpdateConfig = updateRunConfig
    47  }
    48  
    49  func updateRunConfig(c *model.CommandConfig, args []string) bool {
    50  	convertPort := func(value string) int {
    51  		if value != "" {
    52  			port, err := strconv.Atoi(value)
    53  			if err != nil {
    54  				utils.Logger.Fatalf("Failed to parse port as integer: %s", c.Run.Port)
    55  			}
    56  			return port
    57  		}
    58  		return 0
    59  	}
    60  	switch len(args) {
    61  	case 3:
    62  		// Possible combinations
    63  		// revel run [import-path] [run-mode] [port]
    64  		c.Run.ImportPath = args[0]
    65  		c.Run.Mode = args[1]
    66  		c.Run.Port = convertPort(args[2])
    67  	case 2:
    68  		// Possible combinations
    69  		// 1. revel run [import-path] [run-mode]
    70  		// 2. revel run [import-path] [port]
    71  		// 3. revel run [run-mode] [port]
    72  
    73  		// Check to see if the import path evaluates out to something that may be on a gopath
    74  		if runIsImportPath(args[0]) {
    75  			// 1st arg is the import path
    76  			c.Run.ImportPath = args[0]
    77  
    78  			if _, err := strconv.Atoi(args[1]); err == nil {
    79  				// 2nd arg is the port number
    80  				c.Run.Port = convertPort(args[1])
    81  			} else {
    82  				// 2nd arg is the run mode
    83  				c.Run.Mode = args[1]
    84  			}
    85  		} else {
    86  			// 1st arg is the run mode
    87  			c.Run.Mode = args[0]
    88  			c.Run.Port = convertPort(args[1])
    89  		}
    90  	case 1:
    91  		// Possible combinations
    92  		// 1. revel run [import-path]
    93  		// 2. revel run [port]
    94  		// 3. revel run [run-mode]
    95  		if runIsImportPath(args[0]) {
    96  			// 1st arg is the import path
    97  			c.Run.ImportPath = args[0]
    98  		} else if _, err := strconv.Atoi(args[0]); err == nil {
    99  			// 1st arg is the port number
   100  			c.Run.Port = convertPort(args[0])
   101  		} else {
   102  			// 1st arg is the run mode
   103  			c.Run.Mode = args[0]
   104  		}
   105  	case 0:
   106  		// Attempt to set the import path to the current working director.
   107  		if c.Run.ImportPath == "" {
   108  			c.Run.ImportPath, _ = os.Getwd()
   109  		}
   110  	}
   111  	c.Index = model.RUN
   112  	return true
   113  }
   114  
   115  // Returns true if this is an absolute path or a relative gopath
   116  func runIsImportPath(pathToCheck string) bool {
   117  	return utils.DirExists(pathToCheck)
   118  }
   119  
   120  // Called to run the app
   121  func runApp(c *model.CommandConfig) (err error) {
   122  	if c.Run.Mode == "" {
   123  		c.Run.Mode = "dev"
   124  	}
   125  
   126  	revel_path, err := model.NewRevelPaths(c.Run.Mode, c.ImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
   127  	if err != nil {
   128  		return utils.NewBuildIfError(err, "Revel paths")
   129  	}
   130  	if c.Run.Port > -1 {
   131  		revel_path.HTTPPort = c.Run.Port
   132  	} else {
   133  		c.Run.Port = revel_path.HTTPPort
   134  	}
   135  
   136  	utils.Logger.Infof("Running %s (%s) in %s mode\n", revel_path.AppName, revel_path.ImportPath, revel_path.RunMode)
   137  	utils.Logger.Debug("Base path:", "path", revel_path.BasePath)
   138  
   139  	// If the app is run in "watched" mode, use the harness to run it.
   140  	if revel_path.Config.BoolDefault("watch", true) && revel_path.Config.BoolDefault("watch.code", true) {
   141  		utils.Logger.Info("Running in watched mode.")
   142  		runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v}`, revel_path.RunMode, c.Verbose)
   143  		if c.HistoricMode {
   144  			runMode = revel_path.RunMode
   145  		}
   146  		// **** Never returns.
   147  		harness.NewHarness(c, revel_path, runMode, c.Run.NoProxy).Run()
   148  	}
   149  
   150  	// Else, just build and run the app.
   151  	utils.Logger.Debug("Running in live build mode.")
   152  	app, err := harness.Build(c, revel_path)
   153  	if err != nil {
   154  		utils.Logger.Errorf("Failed to build app: %s", err)
   155  	}
   156  	app.Port = revel_path.HTTPPort
   157  	var paths []byte
   158  	if len(app.PackagePathMap) > 0 {
   159  		paths, _ = json.Marshal(app.PackagePathMap)
   160  	}
   161  	runMode := fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v,"packagePathMap":%s}`, app.Paths.RunMode, c.Verbose, string(paths))
   162  	if c.HistoricMode {
   163  		runMode = revel_path.RunMode
   164  	}
   165  	app.Cmd(runMode).Run(c)
   166  	return
   167  }