func (l *Loader) Load(f *appfile.File, dir string) (*appfile.File, error) { realFile := f // Load the "detected" Appfile appDef, err := appfile.Default(dir, l.Detector) if err != nil { return nil, fmt.Errorf("Error detecting app type: %s", err) } // Merge the detected Appfile with the real Appfile var merged appfile.File if err := merged.Merge(appDef); err != nil { return nil, fmt.Errorf("Error loading Appfile: %s", err) } if realFile != nil { if err := merged.Merge(realFile); err != nil { return nil, fmt.Errorf("Error loading Appfile: %s", err) } } realFile = &merged // If we have no application type, there is nothing more to do if realFile == nil || realFile.Application.Type == "" { return realFile, nil } // If we're not configured to do any further detection, return it if !realFile.Application.Detect { return realFile, nil } // Minimally compile the file that we can use to create a core compiled, err := l.Compiler.MinCompile(realFile) if err != nil { return nil, err } // Create a temporary directory we use for the core td, err := ioutil.TempDir("", "otto") if err != nil { return nil, err } defer os.RemoveAll(td) // Create a core core, err := otto.NewCore(&otto.CoreConfig{ DataDir: filepath.Join(td, "data"), LocalDir: filepath.Join(td, "local"), CompileDir: filepath.Join(td, "compile"), Appfile: compiled, Apps: l.Apps, }) if err != nil { return nil, err } // Get the app implementation appImpl, appCtx, err := core.App() if err != nil { return nil, err } defer app.Close(appImpl) // Load the implicit Appfile implicit, err := appImpl.Implicit(appCtx) if err != nil { return nil, err } var final appfile.File if err := final.Merge(appDef); err != nil { return nil, fmt.Errorf("Error loading Appfile: %s", err) } if implicit != nil { if err := final.Merge(implicit); err != nil { return nil, fmt.Errorf("Error loading Appfile: %s", err) } } if f != nil { if err := final.Merge(f); err != nil { return nil, fmt.Errorf("Error loading Appfile: %s", err) } } return &final, nil }