// ConfigureLogging applies the configuration in revel.Config to the glog flags. // Logger flags specified explicitly on the command line are not changed. func ConfigureLogging() { // Get the flags specified on the command line. specifiedFlags := make(map[string]struct{}) flag.Visit(func(f *flag.Flag) { specifiedFlags[f.Name] = struct{}{} }) // For each logger option in app.conf.. var err error for _, option := range Config.Options("log.") { val, _ := Config.String(option) switch flagname := option[len("log."):]; flagname { case "v", "vmodule", "logtostderr", "alsologtostderr", "stderrthreshold", "log_dir": // If it was specified on the command line, don't set it from app.conf if _, ok := specifiedFlags[flagname]; ok { continue } // Look up the flag and set it. // If it's log_dir, make it into an absolute path and creat it if necessary. if flagname == "log_dir" { if val, err = filepath.Abs(val); err != nil { glog.Fatalln("Failed to get absolute path to log_dir:", err) } os.MkdirAll(val, 0777) // Create the log dir if it doesn't already exist. } if err = flag.Set(flagname, val); err != nil { glog.Fatalf("Failed to set glog option for %s=%s: %s", flagname, val, err) } case "maxsize": if glog.MaxSize, err = humanize.ParseBytes(val); err != nil { glog.Fatalf("Failed to parse log.MaxSize=%s: %s", val, err) } } } }
// findSrcPaths uses the "go/build" package to find the source root for Revel // and the app. func findSrcPaths(importPath string) (revelSourcePath, appSourcePath string) { var ( gopaths = filepath.SplitList(build.Default.GOPATH) goroot = build.Default.GOROOT ) if len(gopaths) == 0 { glog.Fatal("GOPATH environment variable is not set. ", "Please refer to http://golang.org/doc/code.html to configure your Go environment.") } if ContainsString(gopaths, goroot) { glog.Fatalf("GOPATH (%s) must not include your GOROOT (%s). "+ "Please refer to http://golang.org/doc/code.html to configure your Go environment.", gopaths, goroot) } appPkg, err := build.Import(importPath, "", build.FindOnly) if err != nil { glog.Fatalln("Failed to import", importPath, "with error:", err) } revelPkg, err := build.Import(REVEL_IMPORT_PATH, "", build.FindOnly) if err != nil { glog.Fatalln("Failed to find Revel with error:", err) } return revelPkg.SrcRoot, appPkg.SrcRoot }
func buildApp(args []string) { if len(args) != 2 { fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long) return } appImportPath, destPath := args[0], args[1] if !revel.Initialized { revel.Init("", appImportPath, "") revel.LoadModules() } os.RemoveAll(destPath) os.MkdirAll(destPath, 0777) app, reverr := harness.Build() panicOnError(reverr, "Failed to build") // Included are: // - run scripts // - binary // - revel // - app // Revel and the app are in a directory structure mirroring import path srcPath := filepath.Join(destPath, "src") tmpRevelPath := filepath.Join(srcPath, filepath.FromSlash(revel.REVEL_IMPORT_PATH)) mustCopyFile(filepath.Join(destPath, filepath.Base(app.BinaryPath)), app.BinaryPath) mustCopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel.RevelPath, "conf"), nil) mustCopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel.RevelPath, "templates"), nil) mustCopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel.BasePath, nil) // Find all the modules used and copy them over. config := revel.Config.Raw() modulePaths := make(map[string]string) // import path => filesystem path for _, section := range config.Sections() { options, _ := config.SectionOptions(section) for _, key := range options { if !strings.HasPrefix(key, "module.") { continue } moduleImportPath, _ := config.String(section, key) if moduleImportPath == "" { continue } modulePath, err := revel.ResolveImportPath(moduleImportPath) if err != nil { glog.Fatalf("Failed to load module %s: %s", key[len("module."):], err) } modulePaths[moduleImportPath] = modulePath } } for importPath, fsPath := range modulePaths { mustCopyDir(filepath.Join(srcPath, filepath.FromSlash(importPath)), fsPath, nil) } tmplData := map[string]interface{}{ "BinName": filepath.Base(app.BinaryPath), "ImportPath": appImportPath, } mustRenderTemplate( filepath.Join(destPath, "run.sh"), filepath.Join(revel.RevelPath, "revel", "package_run.sh.template"), tmplData) mustRenderTemplate( filepath.Join(destPath, "run.bat"), filepath.Join(revel.RevelPath, "revel", "package_run.bat.template"), tmplData) }
// Build the app: // 1. Generate the the main.go file. // 2. Run the appropriate "go build" command. // Requires that revel.Init has been called previously. // Returns the path to the built binary, and an error if there was a problem building it. func Build() (app *App, compileError *revel.Error) { start := time.Now() // First, clear the generated files (to avoid them messing with ProcessSource). cleanSource("tmp", "routes") sourceInfo, compileError := ProcessSource(revel.CodePaths) if compileError != nil { return nil, compileError } // Add the db.import to the import paths. if dbImportPath, found := revel.Config.String("db.import"); found { sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, dbImportPath) } // Generate two source files. templateArgs := map[string]interface{}{ "Controllers": sourceInfo.ControllerSpecs(), "ValidationKeys": sourceInfo.ValidationKeys, "ImportPaths": calcImportAliases(sourceInfo), "TestSuites": sourceInfo.TestSuites(), } genSource("tmp", "main.go", MAIN, templateArgs) genSource("routes", "routes.go", ROUTES, templateArgs) // Read build config. buildTags := revel.Config.StringDefault("build.tags", "") // Build the user program (all code under app). // It relies on the user having "go" installed. goPath, err := exec.LookPath("go") if err != nil { glog.Fatalf("Go executable not found in PATH.") } pkg, err := build.Default.Import(revel.ImportPath, "", build.FindOnly) if err != nil { glog.Fatalln("Failure importing", revel.ImportPath) } binName := filepath.Join(pkg.BinDir, filepath.Base(revel.BasePath)) if runtime.GOOS == "windows" { binName += ".exe" } gotten := make(map[string]struct{}) for { buildCmd := exec.Command(goPath, "build", "-i", "-tags", buildTags, "-o", binName, path.Join(revel.ImportPath, "app", "tmp")) glog.V(1).Infoln("Exec:", buildCmd.Args) output, err := buildCmd.CombinedOutput() // If the build succeeded, we're done. if err == nil { glog.Infof("Build took %s", time.Since(start)) return NewApp(binName), nil } glog.Error(string(output)) // See if it was an import error that we can go get. matches := importErrorPattern.FindStringSubmatch(string(output)) if matches == nil { return nil, newCompileError(output) } // Ensure we haven't already tried to go get it. pkgName := matches[1] if _, alreadyTried := gotten[pkgName]; alreadyTried { return nil, newCompileError(output) } gotten[pkgName] = struct{}{} // Execute "go get <pkg>" getCmd := exec.Command(goPath, "get", pkgName) glog.V(1).Infoln("Exec:", getCmd.Args) getOutput, err := getCmd.CombinedOutput() if err != nil { glog.Error(string(getOutput)) return nil, newCompileError(output) } // Success getting the import, attempt to build again. } glog.Fatal("Not reachable") return nil, nil }