func (c *CompileCommand) Run(args []string) int { var flagAppfile string fs := c.FlagSet("compile", FlagSetNone) fs.Usage = func() { c.Ui.Error(c.Help()) } //把参数--appfile的值写入&flagAppfile fs.StringVar(&flagAppfile, "appfile", "", "") if err := fs.Parse(args); err != nil { return 1 } // Load a UI ui := c.OttoUi() ui.Header("装载 Appfile...") fmt.Printf("[KuuYee]====> flagAppfile: %+v\n", flagAppfile) app, appPath, err := loadAppfile(flagAppfile) if err != nil { c.Ui.Error(err.Error()) return 1 } fmt.Printf("[KuuYee]====> appPath: %+v\n", appPath) // 如果没有Appfile,告诉用户发生了什么 if app == nil { ui.Header("没有发现Appfile! Detecting project information...") ui.Message(fmt.Sprintf( "No Appfile was found. If there is no Appfile, Otto will do its best\n" + "to detect the type of application this is and set reasonable defaults.\n" + "This is a good way to get started with Otto, but over time we recommend\n" + "writing a real Appfile since this will allow more complex customizations,\n" + "the ability to reference dependencies, versioning, and more.")) } // 解析 dataDir, err := c.DataDir() if err != nil { c.Ui.Error(err.Error()) return 1 } fmt.Printf("[KuuYee]====> dataDir: %+v\n", dataDir) detectorDir := filepath.Join(dataDir, DefaultLocalDataDetectorDir) fmt.Printf("[KuuYee]====> detectorDir: %+v\n", detectorDir) log.Printf("[DEBUG] loading detectors from: %s", detectorDir) detectConfig, err := detect.ParseDir(detectorDir) //如果没有找到定制配置,则从这里开始分析 if err != nil { c.Ui.Error(err.Error()) return 1 } if detectConfig == nil { detectConfig = &detect.Config{} fmt.Printf("[KuuYee]====> detectConfig: %+v\n", detectConfig) } err = detectConfig.Merge(&detect.Config{Detectors: c.Detectors}) if err != nil { c.Ui.Error(err.Error()) return 1 } //打印能够发现的类型 for i, v := range detectConfig.Detectors { fmt.Printf("[KuuYee]====> detectConfig %d : %+v\n", i, v) } // 装载默认Appfile,我们可以合并任何的默认 // appfile到已经装载的Appfile appDef, err := appfile.Default(appPath, detectConfig) if err != nil { c.Ui.Error(fmt.Sprintf( "装载Appfile报错:%s", err)) return 1 } fmt.Printf("[KuuYee]====> appDef: %+v\n", appDef) // 如果没有加载到appfile,那么认为没有可用的应用 if app == nil && appDef.Application.Type == "" { c.Ui.Error(strings.TrimSpace(errCantDetectType)) return 1 } // 合并应用 if app != nil { if err := appDef.Merge(app); err != nil { c.Ui.Error(fmt.Sprintf( "装载Appfile报错: %s", err)) return 1 } } app = appDef fmt.Printf("[KuuYee]====> app: %+v\n", app) // 编译Appfile ui.Header("获取所有的Appfile依赖...") capp, err := appfile.Compile(app, &appfile.CompileOpts{ Dir: filepath.Join(filepath.Dir(app.Path), DefaultOutputDir, DefaultOutputDirCompiledAppfile), Detect: detectConfig, Callback: c.compileCallback(ui), }) if err != nil { c.Ui.Error(fmt.Sprintf( "编译Appfile报错:%s", err)) return 1 } // 取得一个Core core, err := c.Core(capp) if err != nil { c.Ui.Error(fmt.Sprintf( "装载Core报错:%s", err)) return 1 } // 取得可用的infrastucture,仅仅为了UI infra := app.ActiveInfrastructure() // 编译之前,告诉用户what is going on ui.Header("编译...") ui.Message(fmt.Sprintf( "Application: %s (%s)", app.Application.Name, app.Application.Type)) ui.Message(fmt.Sprintf("项目: %s", app.Project.Name)) ui.Message(fmt.Sprintf( "Infrastructure: %s (%s)", infra.Type, infra.Flavor)) ui.Message("") // 开始编译 if err := core.Compile(); err != nil { c.Ui.Error(fmt.Sprintf( "编译报错: %s", err)) return 1 } // Success! ui.Header("[green]编译成功!") ui.Message(fmt.Sprintf( "[green]This means that Otto is now ready to start a development environment,\n" + "deploy this application, build the supporting infrastructure, and\n" + "more. See the help for more information.\n\n" + "Supporting files to enable Otto to manage your application from\n" + "development to deployment have been placed in the output directory.\n" + "These files can be manually inspected to determine what Otto will do.")) return 0 }
func (c *CompileCommand) Run(args []string) int { var flagAppfile string fs := c.FlagSet("compile", FlagSetNone) fs.Usage = func() { c.Ui.Error(c.Help()) } fs.StringVar(&flagAppfile, "appfile", "", "") if err := fs.Parse(args); err != nil { return 1 } // Load all the plugins, we use all the plugins for compilation only // so we have full access to detectors and app types. pluginMgr, err := c.PluginManager() if err != nil { c.Ui.Error(fmt.Sprintf( "Error initializing plugin manager: %s", err)) return 1 } if err := pluginMgr.LoadAll(); err != nil { c.Ui.Error(fmt.Sprintf( "Error loading plugins: %s", err)) return 1 } // Load the detectors from the plugins detectors := make([]*detect.Detector, 0, 20) detectors = append(detectors, c.Detectors...) for _, p := range pluginMgr.Plugins() { detectors = append(detectors, p.AppMeta.Detectors...) } // Parse the detectors dataDir, err := c.DataDir() if err != nil { c.Ui.Error(err.Error()) return 1 } detectorDir := filepath.Join(dataDir, DefaultLocalDataDetectorDir) log.Printf("[DEBUG] loading detectors from: %s", detectorDir) detectConfig, err := detect.ParseDir(detectorDir) if err != nil { c.Ui.Error(err.Error()) return 1 } if detectConfig == nil { detectConfig = &detect.Config{} } err = detectConfig.Merge(&detect.Config{Detectors: detectors}) if err != nil { c.Ui.Error(err.Error()) return 1 } // Load a UI ui := c.OttoUi() ui.Header("Loading Appfile...") app, appPath, err := loadAppfile(flagAppfile) if err != nil { c.Ui.Error(err.Error()) return 1 } // Tell the user what is happening if they have no Appfile if app == nil { ui.Header("No Appfile found! Detecting project information...") ui.Message(fmt.Sprintf( "No Appfile was found. If there is no Appfile, Otto will do its best\n" + "to detect the type of application this is and set reasonable defaults.\n" + "This is a good way to get started with Otto, but over time we recommend\n" + "writing a real Appfile since this will allow more complex customizations,\n" + "the ability to reference dependencies, versioning, and more.")) } // Build the appfile compiler var loader appfileLoad.Loader compiler, err := appfile.NewCompiler(&appfile.CompileOpts{ Dir: filepath.Join( appPath, DefaultOutputDir, DefaultOutputDirCompiledAppfile), Loader: loader.Load, Callback: c.compileCallback(ui), }) if err != nil { c.Ui.Error(fmt.Sprintf( "Error initializing Appfile compiler: %s", err)) return 1 } // Create the Appfile loader if err := pluginMgr.ConfigureCore(c.CoreConfig); err != nil { panic(err) } loader.Detector = detectConfig loader.Compiler = compiler loader.Apps = c.CoreConfig.Apps // Load the complete Appfile app, err = loader.Load(app, appPath) if err != nil { c.Ui.Error(err.Error()) return 1 } // If there was no loaded Appfile and we don't have an application // type then we weren't able to detect the type. Error. if app == nil || app.Application.Type == "" { c.Ui.Error(strings.TrimSpace(errCantDetectType)) return 1 } // Compile the Appfile ui.Header("Fetching all Appfile dependencies...") capp, err := compiler.Compile(app) if err != nil { c.Ui.Error(fmt.Sprintf( "Error compiling Appfile: %s", err)) return 1 } // Get a core core, err := c.Core(capp) if err != nil { c.Ui.Error(fmt.Sprintf( "Error loading core: %s", err)) return 1 } // Get the active infrastructure just for UI reasons infra := app.ActiveInfrastructure() // Before the compilation, output to the user what is going on ui.Header("Compiling...") ui.Message(fmt.Sprintf( "Application: %s (%s)", app.Application.Name, app.Application.Type)) ui.Message(fmt.Sprintf("Project: %s", app.Project.Name)) ui.Message(fmt.Sprintf( "Infrastructure: %s (%s)", infra.Type, infra.Flavor)) ui.Message("") // Compile! if err := core.Compile(); err != nil { c.Ui.Error(fmt.Sprintf( "Error compiling: %s", err)) return 1 } // Store the used plugins so later calls don't have to load everything usedPath, err := c.AppfilePluginsPath(capp) if err != nil { c.Ui.Error(fmt.Sprintf( "Error compiling: %s", err)) return 1 } if err := pluginMgr.StoreUsed(usedPath); err != nil { c.Ui.Error(fmt.Sprintf( "Error compiling plugin data: %s", err)) return 1 } // Success! ui.Header("[green]Compilation success!") ui.Message(fmt.Sprintf( "[green]This means that Otto is now ready to start a development environment,\n" + "deploy this application, build the supporting infrastructure, and\n" + "more. See the help for more information.\n\n" + "Supporting files to enable Otto to manage your application from\n" + "development to deployment have been placed in the output directory.\n" + "These files can be manually inspected to determine what Otto will do.")) return 0 }
func (c *CompileCommand) Run(args []string) int { var flagAppfile string fs := c.FlagSet("compile", FlagSetNone) fs.Usage = func() { c.Ui.Error(c.Help()) } fs.StringVar(&flagAppfile, "appfile", "", "") if err := fs.Parse(args); err != nil { return 1 } // Load a UI ui := c.OttoUi() ui.Header("Loading Appfile...") // Determine all the Appfile paths // // First, if an Appfile was specified on the command-line, it must // exist so we validate that it exists. if flagAppfile != "" { fi, err := os.Stat(flagAppfile) if err != nil { c.Ui.Error(fmt.Sprintf( "Error loading Appfile: %s", err)) return 1 } if fi.IsDir() { flagAppfile = filepath.Join(flagAppfile, DefaultAppfile) } } // If the Appfile is still blank, just use our current directory if flagAppfile == "" { var err error flagAppfile, err = os.Getwd() if err != nil { c.Ui.Error(fmt.Sprintf( "Error loading working directory: %s", err)) return 1 } flagAppfile = filepath.Join(flagAppfile, DefaultAppfile) } // If we have the Appfile, then make sure it is an absoute path if flagAppfile != "" { var err error flagAppfile, err = filepath.Abs(flagAppfile) if err != nil { c.Ui.Error(fmt.Sprintf( "Error getting Appfile path: %s", err)) return 1 } } // Load the appfile. This is the only time we ever load the // raw Appfile. All other commands load the compiled Appfile. var app *appfile.File if fi, err := os.Stat(flagAppfile); err == nil && !fi.IsDir() { app, err = appfile.ParseFile(flagAppfile) if err != nil { c.Ui.Error(err.Error()) return 1 } } // Tell the user what is happening if they have no Appfile if app == nil { ui.Header("No Appfile found! Detecting project information...") ui.Message(fmt.Sprintf( "No Appfile was found. If there is no Appfile, Otto will do its best\n" + "to detect the type of application this is and set reasonable defaults.\n" + "This is a good way to get started with Otto, but over time we recommend\n" + "writing a real Appfile since this will allow more complex customizations,\n" + "the ability to reference dependencies, versioning, and more.")) } // Parse the detectors dataDir, err := c.DataDir() if err != nil { c.Ui.Error(err.Error()) return 1 } detectorDir := filepath.Join(dataDir, DefaultLocalDataDetectorDir) log.Printf("[DEBUG] loading detectors from: %s", detectorDir) detectConfig, err := detect.ParseDir(detectorDir) if err != nil { c.Ui.Error(err.Error()) return 1 } if detectConfig == nil { detectConfig = &detect.Config{} } err = detectConfig.Merge(&detect.Config{Detectors: c.Detectors}) if err != nil { c.Ui.Error(err.Error()) return 1 } // Load the default Appfile so we can merge in any defaults into // the loaded Appfile (if there is one). appDef, err := appfile.Default(filepath.Dir(flagAppfile), detectConfig) if err != nil { c.Ui.Error(fmt.Sprintf( "Error loading Appfile: %s", err)) return 1 } // If there was no loaded Appfile and we don't have an application // type then we weren't able to detect the type. Error. if app == nil && appDef.Application.Type == "" { c.Ui.Error(strings.TrimSpace(errCantDetectType)) return 1 } // Merge the appfiles if app != nil { if err := appDef.Merge(app); err != nil { c.Ui.Error(fmt.Sprintf( "Error loading Appfile: %s", err)) return 1 } } app = appDef // Compile the Appfile ui.Header("Fetching all Appfile dependencies...") capp, err := appfile.Compile(app, &appfile.CompileOpts{ Dir: filepath.Join( filepath.Dir(app.Path), DefaultOutputDir, DefaultOutputDirCompiledAppfile), Detect: detectConfig, Callback: c.compileCallback(ui), }) if err != nil { c.Ui.Error(fmt.Sprintf( "Error compiling Appfile: %s", err)) return 1 } // Get a core core, err := c.Core(capp) if err != nil { c.Ui.Error(fmt.Sprintf( "Error loading core: %s", err)) return 1 } // Get the active infrastructure just for UI reasons infra := app.ActiveInfrastructure() // Before the compilation, output to the user what is going on ui.Header("Compiling...") ui.Message(fmt.Sprintf( "Application: %s (%s)", app.Application.Name, app.Application.Type)) ui.Message(fmt.Sprintf("Project: %s", app.Project.Name)) ui.Message(fmt.Sprintf( "Infrastructure: %s (%s)", infra.Type, infra.Flavor)) ui.Message("") // Compile! if err := core.Compile(); err != nil { c.Ui.Error(fmt.Sprintf( "Error compiling: %s", err)) return 1 } // Success! ui.Header("[green]Compilation success!") ui.Message(fmt.Sprintf( "[green]This means that Otto is now ready to start a development environment,\n" + "deploy this application, build the supporting infastructure, and\n" + "more. See the help for more information.\n\n" + "Supporting files to enable Otto to manage your application from\n" + "development to deployment have been placed in the output directory.\n" + "These files can be manually inspected to determine what Otto will do.")) return 0 }