mirror of
https://github.com/kevin-DL/revel-cmd.git
synced 2026-01-11 18:54:31 +00:00
24
.travis.yml
24
.travis.yml
@@ -47,19 +47,25 @@ script:
|
|||||||
#- revel package my/testapp prod
|
#- revel package my/testapp prod
|
||||||
|
|
||||||
# Ensure the new-app flow works (plus the other commands).
|
# Ensure the new-app flow works (plus the other commands).
|
||||||
- revel new --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
|
- revel new --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 --package revelframework.com -v
|
||||||
- revel test --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
|
- revel test --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v
|
||||||
- revel clean --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
|
- revel clean --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v
|
||||||
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v -t build/testapp2
|
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v -t build/testapp2
|
||||||
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v -t build/testapp2 -m prod
|
- revel build --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v -t build/testapp2 -m prod
|
||||||
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v
|
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v
|
||||||
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@develop" -a my/testapp2 -v -m prod
|
- revel package --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp2 -v -m prod
|
||||||
|
|
||||||
|
- export INITIALWD=$PWD
|
||||||
# Check build works with no-vendor flag
|
# Check build works with no-vendor flag
|
||||||
- cd $GOPATH
|
- cd $GOPATH
|
||||||
- export GO111MODULE=auto
|
- export GO111MODULE=auto
|
||||||
- revel new -a my/testapp2 --no-vendor
|
- revel new -a my/testapp2 --no-vendor -v
|
||||||
- revel test -a my/testapp2
|
- revel test -a my/testapp2 -v
|
||||||
|
|
||||||
|
# Check non verbose build, outside of GO path
|
||||||
|
- cd $INITIALWD
|
||||||
|
- revel new --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp3 --package revelframework.com
|
||||||
|
- revel test --gomod-flags "edit -replace=github.com/revel/revel=github.com/revel/revel@$REVEL_BRANCH" -a my/testapp3
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ func (cmd AppCmd) Kill() {
|
|||||||
if cmd.Cmd != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited()) {
|
if cmd.Cmd != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited()) {
|
||||||
// Windows appears to send the kill to all threads, shutting down the
|
// Windows appears to send the kill to all threads, shutting down the
|
||||||
// server before this can, this check will ensure the process is still running
|
// server before this can, this check will ensure the process is still running
|
||||||
if _, err := os.FindProcess(int(cmd.Process.Pid));err!=nil {
|
if _, err := os.FindProcess(int(cmd.Process.Pid)); err != nil {
|
||||||
// Server has already exited
|
// Server has already exited
|
||||||
utils.Logger.Info("Server not running revel server pid", "pid", cmd.Process.Pid)
|
utils.Logger.Info("Server not running revel server pid", "pid", cmd.Process.Pid)
|
||||||
return
|
return
|
||||||
@@ -143,9 +143,9 @@ func (cmd AppCmd) Kill() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Logger.Error(
|
utils.Logger.Info(
|
||||||
"Revel app failed to kill process.",
|
"Revel app already exited.",
|
||||||
"processid", cmd.Process.Pid,"error",err,
|
"processid", cmd.Process.Pid, "error", err,
|
||||||
"killerror", cmd.Process.Kill())
|
"killerror", cmd.Process.Kill())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package harness
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@@ -56,6 +57,8 @@ type Harness struct {
|
|||||||
paths *model.RevelContainer // The Revel container
|
paths *model.RevelContainer // The Revel container
|
||||||
config *model.CommandConfig // The configuration
|
config *model.CommandConfig // The configuration
|
||||||
runMode string // The runmode the harness is running in
|
runMode string // The runmode the harness is running in
|
||||||
|
isError bool // True if harness is in error state
|
||||||
|
ranOnce bool // True app compiled once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err error) {
|
func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err error) {
|
||||||
@@ -202,6 +205,21 @@ func NewHarness(c *model.CommandConfig, paths *model.RevelContainer, runMode str
|
|||||||
// Refresh method rebuilds the Revel application and run it on the given port.
|
// Refresh method rebuilds the Revel application and run it on the given port.
|
||||||
// called by the watcher
|
// called by the watcher
|
||||||
func (h *Harness) Refresh() (err *utils.SourceError) {
|
func (h *Harness) Refresh() (err *utils.SourceError) {
|
||||||
|
t := time.Now();
|
||||||
|
fmt.Println("Changed detected, recompiling")
|
||||||
|
err = h.refresh()
|
||||||
|
if err!=nil && !h.ranOnce && h.useProxy {
|
||||||
|
addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort)
|
||||||
|
|
||||||
|
fmt.Printf("\nError compiling code, to view error details see proxy running on http://%s\n\n",addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.ranOnce = true
|
||||||
|
fmt.Printf("\nTime to recompile %s\n",time.Now().Sub(t).String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) refresh() (err *utils.SourceError) {
|
||||||
// Allow only one thread to rebuild the process
|
// Allow only one thread to rebuild the process
|
||||||
// If multiple requests to rebuild are queued only the last one is executed on
|
// If multiple requests to rebuild are queued only the last one is executed on
|
||||||
// So before a build is started we wait for a second to determine if
|
// So before a build is started we wait for a second to determine if
|
||||||
@@ -281,7 +299,8 @@ func (h *Harness) Run() {
|
|||||||
paths = append(paths, h.paths.CodePaths...)
|
paths = append(paths, h.paths.CodePaths...)
|
||||||
h.watcher = watcher.NewWatcher(h.paths, false)
|
h.watcher = watcher.NewWatcher(h.paths, false)
|
||||||
h.watcher.Listen(h, paths...)
|
h.watcher.Listen(h, paths...)
|
||||||
h.watcher.Notify()
|
go h.Refresh()
|
||||||
|
// h.watcher.Notify()
|
||||||
|
|
||||||
if h.useProxy {
|
if h.useProxy {
|
||||||
go func() {
|
go func() {
|
||||||
@@ -292,6 +311,7 @@ func (h *Harness) Run() {
|
|||||||
addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort)
|
addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort)
|
||||||
utils.Logger.Infof("Proxy server is listening on %s", addr)
|
utils.Logger.Infof("Proxy server is listening on %s", addr)
|
||||||
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if h.paths.HTTPSsl {
|
if h.paths.HTTPSsl {
|
||||||
err = http.ListenAndServeTLS(
|
err = http.ListenAndServeTLS(
|
||||||
@@ -308,13 +328,15 @@ func (h *Harness) Run() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
// Kill the app on signal.
|
|
||||||
|
// Make a new channel to listen for the interrupt event
|
||||||
ch := make(chan os.Signal)
|
ch := make(chan os.Signal)
|
||||||
signal.Notify(ch, os.Interrupt, os.Kill)
|
signal.Notify(ch, os.Interrupt, os.Kill)
|
||||||
<-ch
|
// Kill the app and exit
|
||||||
if h.app != nil {
|
if h.app != nil {
|
||||||
h.app.Kill()
|
h.app.Kill()
|
||||||
}
|
}
|
||||||
|
<-ch
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,8 +174,10 @@ func (c *CommandConfig) initAppFolder() (err error) {
|
|||||||
|
|
||||||
// Use app folder to read the go.mod if it exists and extract the package information
|
// Use app folder to read the go.mod if it exists and extract the package information
|
||||||
goModFile := filepath.Join(appFolder, "go.mod")
|
goModFile := filepath.Join(appFolder, "go.mod")
|
||||||
|
utils.Logger.Info("Checking gomod, extracting from file", "path", goModFile,"exists", utils.Exists(goModFile))
|
||||||
if utils.Exists(goModFile) {
|
if utils.Exists(goModFile) {
|
||||||
c.Vendored = true
|
c.Vendored = true
|
||||||
|
utils.Logger.Info("Found go mod, extracting from file", "path", goModFile)
|
||||||
file, err := ioutil.ReadFile(goModFile)
|
file, err := ioutil.ReadFile(goModFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -220,7 +222,7 @@ func (c *CommandConfig) initAppFolder() (err error) {
|
|||||||
c.AppPath = appFolder
|
c.AppPath = appFolder
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.Logger.Info("Set application path", "path", c.AppPath)
|
utils.Logger.Info("Set application path", "path", c.AppPath, "vendored",c.Vendored, "importpath",c.ImportPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,6 +235,7 @@ func (c *CommandConfig) InitPackageResolver() {
|
|||||||
c.PackageResolver = func(pkgName string) error {
|
c.PackageResolver = func(pkgName string) error {
|
||||||
utils.Logger.Info("Request for package ", "package", pkgName, "use vendor", c.Vendored)
|
utils.Logger.Info("Request for package ", "package", pkgName, "use vendor", c.Vendored)
|
||||||
var getCmd *exec.Cmd
|
var getCmd *exec.Cmd
|
||||||
|
print("Downloading related packages ...")
|
||||||
if c.Vendored {
|
if c.Vendored {
|
||||||
getCmd = exec.Command(c.GoCmd, "mod", "tidy")
|
getCmd = exec.Command(c.GoCmd, "mod", "tidy")
|
||||||
} else {
|
} else {
|
||||||
@@ -246,6 +249,7 @@ func (c *CommandConfig) InitPackageResolver() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Logger.Error("Failed to import package", "error", err, "gopath", build.Default.GOPATH, "GO-ROOT", build.Default.GOROOT, "output", string(output))
|
utils.Logger.Error("Failed to import package", "error", err, "gopath", build.Default.GOPATH, "GO-ROOT", build.Default.GOROOT, "output", string(output))
|
||||||
}
|
}
|
||||||
|
println(" completed.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered
|
|||||||
|
|
||||||
// Look through the embedded types to see if the current type is among them.
|
// Look through the embedded types to see if the current type is among them.
|
||||||
for _, embeddedType := range spec.EmbeddedTypes {
|
for _, embeddedType := range spec.EmbeddedTypes {
|
||||||
|
|
||||||
// If so, add this type's simple name to the nodeQueue, and its spec to
|
// If so, add this type's simple name to the nodeQueue, and its spec to
|
||||||
// the filtered list.
|
// the filtered list.
|
||||||
if typeSimpleName == embeddedType.String() {
|
if typeSimpleName == embeddedType.String() {
|
||||||
@@ -111,6 +110,7 @@ func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered
|
|||||||
// ControllerSpecs returns the all the controllers that embeds
|
// ControllerSpecs returns the all the controllers that embeds
|
||||||
// `revel.Controller`
|
// `revel.Controller`
|
||||||
func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
|
func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
|
||||||
|
utils.Logger.Info("Scanning controller specifications for types ","typePath",RevelImportPath + ".Controller", "speclen",len(s.controllerSpecs))
|
||||||
if s.controllerSpecs == nil {
|
if s.controllerSpecs == nil {
|
||||||
s.controllerSpecs = s.TypesThatEmbed(RevelImportPath + ".Controller", "controllers")
|
s.controllerSpecs = s.TypesThatEmbed(RevelImportPath + ".Controller", "controllers")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"go/token"
|
"go/token"
|
||||||
"strings"
|
"strings"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"github.com/revel/cmd/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -31,14 +32,21 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m
|
|||||||
strings.Contains(p.PkgPath, "/tests/")
|
strings.Contains(p.PkgPath, "/tests/")
|
||||||
methodMap = map[string][]*model.MethodSpec{}
|
methodMap = map[string][]*model.MethodSpec{}
|
||||||
)
|
)
|
||||||
|
localImportMap := map[string]string{}
|
||||||
|
log := s.sourceProcessor.log.New("package", p.PkgPath)
|
||||||
|
log.Info("Processing package")
|
||||||
for _, tree := range p.Syntax {
|
for _, tree := range p.Syntax {
|
||||||
for _, decl := range tree.Decls {
|
for _, decl := range tree.Decls {
|
||||||
|
|
||||||
s.sourceProcessor.packageMap[p.PkgPath] = filepath.Dir(p.Fset.Position(decl.Pos()).Filename)
|
s.sourceProcessor.packageMap[p.PkgPath] = filepath.Dir(p.Fset.Position(decl.Pos()).Filename)
|
||||||
//println("*** checking", p.Fset.Position(decl.Pos()).Filename)
|
if !s.addImport(decl, p, localImportMap, log) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
spec, found := s.getStructTypeDecl(decl, p.Fset)
|
spec, found := s.getStructTypeDecl(decl, p.Fset)
|
||||||
|
//log.Info("Checking file","filename", p.Fset.Position(decl.Pos()).Filename,"found",found)
|
||||||
if found {
|
if found {
|
||||||
if isController || isTest {
|
if isController || isTest {
|
||||||
controllerSpec := s.getControllerSpec(spec, p)
|
controllerSpec := s.getControllerSpec(spec, p, localImportMap)
|
||||||
sourceInfo.StructSpecs = append(sourceInfo.StructSpecs, controllerSpec)
|
sourceInfo.StructSpecs = append(sourceInfo.StructSpecs, controllerSpec)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -56,7 +64,7 @@ func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *m
|
|||||||
// return one result
|
// return one result
|
||||||
if m, receiver := s.getControllerFunc(funcDecl, p); m != nil {
|
if m, receiver := s.getControllerFunc(funcDecl, p); m != nil {
|
||||||
methodMap[receiver] = append(methodMap[receiver], m)
|
methodMap[receiver] = append(methodMap[receiver], m)
|
||||||
s.sourceProcessor.log.Info("Added method map to ", "receiver", receiver, "method", m.Name)
|
log.Info("Added method map to ", "receiver", receiver, "method", m.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for validation
|
// Check for validation
|
||||||
@@ -271,7 +279,7 @@ func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packa
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.Package) (controllerSpec *model.TypeInfo) {
|
func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.Package, localImportMap map[string]string) (controllerSpec *model.TypeInfo) {
|
||||||
structType := spec.Type.(*ast.StructType)
|
structType := spec.Type.(*ast.StructType)
|
||||||
|
|
||||||
// At this point we know it's a type declaration for a struct.
|
// At this point we know it's a type declaration for a struct.
|
||||||
@@ -282,6 +290,7 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.
|
|||||||
ImportPath: p.PkgPath,
|
ImportPath: p.PkgPath,
|
||||||
PackageName: p.Name,
|
PackageName: p.Name,
|
||||||
}
|
}
|
||||||
|
log := s.sourceProcessor.log.New("file", p.Fset.Position(spec.Pos()).Filename, "position", p.Fset.Position(spec.Pos()).Line)
|
||||||
for _, field := range structType.Fields.List {
|
for _, field := range structType.Fields.List {
|
||||||
// If field.Names is set, it's not an embedded type.
|
// If field.Names is set, it's not an embedded type.
|
||||||
if field.Names != nil {
|
if field.Names != nil {
|
||||||
@@ -329,9 +338,12 @@ func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.
|
|||||||
importPath = p.PkgPath
|
importPath = p.PkgPath
|
||||||
} else {
|
} else {
|
||||||
var ok bool
|
var ok bool
|
||||||
if importPath, ok = s.sourceProcessor.importMap[pkgName]; !ok {
|
if importPath, ok = localImportMap[pkgName]; !ok {
|
||||||
s.sourceProcessor.log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap)
|
log.Debug("Debug: Unusual, failed to find package locally ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", )
|
||||||
continue
|
if importPath, ok = s.sourceProcessor.importMap[pkgName]; !ok {
|
||||||
|
log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", )
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,4 +388,37 @@ func (s *SourceInfoProcessor) getFuncName(funcDecl *ast.FuncDecl) string {
|
|||||||
prefix += "."
|
prefix += "."
|
||||||
}
|
}
|
||||||
return prefix + funcDecl.Name.Name
|
return prefix + funcDecl.Name.Name
|
||||||
|
}
|
||||||
|
func (s *SourceInfoProcessor) addImport(decl ast.Decl, p *packages.Package, localImportMap map[string]string, log logger.MultiLogger) (shouldContinue bool) {
|
||||||
|
shouldContinue = true
|
||||||
|
genDecl, ok := decl.(*ast.GenDecl)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if genDecl.Tok == token.IMPORT {
|
||||||
|
shouldContinue = false
|
||||||
|
for _, spec := range genDecl.Specs {
|
||||||
|
importSpec := spec.(*ast.ImportSpec)
|
||||||
|
//fmt.Printf("*** import specification %#v\n", importSpec)
|
||||||
|
var pkgAlias string
|
||||||
|
if importSpec.Name != nil {
|
||||||
|
pkgAlias = importSpec.Name.Name
|
||||||
|
if pkgAlias == "_" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
|
||||||
|
fullPath := quotedPath[1 : len(quotedPath) - 1] // Remove the quotes
|
||||||
|
if pkgAlias == "" {
|
||||||
|
pkgAlias = fullPath
|
||||||
|
if index := strings.LastIndex(pkgAlias, "/"); index > 0 {
|
||||||
|
pkgAlias = pkgAlias[index + 1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localImportMap[pkgAlias] = fullPath
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,18 @@
|
|||||||
package parser2
|
package parser2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
|
||||||
"go/token"
|
|
||||||
"github.com/revel/cmd/model"
|
"github.com/revel/cmd/model"
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
"github.com/revel/cmd/utils"
|
"github.com/revel/cmd/utils"
|
||||||
"errors"
|
"go/parser"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/revel/cmd/logger"
|
"github.com/revel/cmd/logger"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"go/scanner"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -33,10 +36,6 @@ func ProcessSource(revelContainer *model.RevelContainer) (sourceInfo *model.Sour
|
|||||||
processor.log.Infof("From parsers : Structures:%d InitImports:%d ValidationKeys:%d %v", len(sourceInfo.StructSpecs), len(sourceInfo.InitImportPaths), len(sourceInfo.ValidationKeys), sourceInfo.PackageMap)
|
processor.log.Infof("From parsers : Structures:%d InitImports:%d ValidationKeys:%d %v", len(sourceInfo.StructSpecs), len(sourceInfo.InitImportPaths), len(sourceInfo.ValidationKeys), sourceInfo.PackageMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
if false {
|
|
||||||
compileError = errors.New("Incompleted")
|
|
||||||
utils.Logger.Panic("Not implemented")
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,16 +44,20 @@ func NewSourceProcessor(revelContainer *model.RevelContainer) *SourceProcessor {
|
|||||||
s.sourceInfoProcessor = NewSourceInfoProcessor(s)
|
s.sourceInfoProcessor = NewSourceInfoProcessor(s)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SourceProcessor) parse() (compileError error) {
|
func (s *SourceProcessor) parse() (compileError error) {
|
||||||
|
print("Parsing packages, (may require download if not cached)...")
|
||||||
if compileError = s.addPackages(); compileError != nil {
|
if compileError = s.addPackages(); compileError != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
println(" Completed")
|
||||||
if compileError = s.addImportMap(); compileError != nil {
|
if compileError = s.addImportMap(); compileError != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if compileError = s.addSourceInfo(); compileError != nil {
|
if compileError = s.addSourceInfo(); compileError != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.sourceInfo.PackageMap = map[string]string{}
|
s.sourceInfo.PackageMap = map[string]string{}
|
||||||
getImportFromMap := func(packagePath string) string {
|
getImportFromMap := func(packagePath string) string {
|
||||||
for path := range s.packageMap {
|
for path := range s.packageMap {
|
||||||
@@ -73,11 +76,15 @@ func (s *SourceProcessor) parse() (compileError error) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Using the packages.Load function load all the packages and type specifications (forces compile).
|
||||||
|
// this sets the SourceProcessor.packageList []*packages.Package
|
||||||
func (s *SourceProcessor) addPackages() (err error) {
|
func (s *SourceProcessor) addPackages() (err error) {
|
||||||
allPackages := []string{s.revelContainer.ImportPath + "/...", model.RevelImportPath}
|
allPackages := []string{model.RevelImportPath + "/..."}
|
||||||
for _, module := range s.revelContainer.ModulePathMap {
|
for _, module := range s.revelContainer.ModulePathMap {
|
||||||
allPackages = append(allPackages, module.ImportPath + "/...") // +"/app/controllers/...")
|
allPackages = append(allPackages, module.ImportPath + "/...") // +"/app/controllers/...")
|
||||||
}
|
}
|
||||||
|
s.log.Info("Reading packages", "packageList", allPackages)
|
||||||
//allPackages = []string{s.revelContainer.ImportPath + "/..."} //+"/app/controllers/..."}
|
//allPackages = []string{s.revelContainer.ImportPath + "/..."} //+"/app/controllers/..."}
|
||||||
|
|
||||||
config := &packages.Config{
|
config := &packages.Config{
|
||||||
@@ -102,9 +109,115 @@ func (s *SourceProcessor) addPackages() (err error) {
|
|||||||
Dir:s.revelContainer.AppPath,
|
Dir:s.revelContainer.AppPath,
|
||||||
}
|
}
|
||||||
s.packageList, err = packages.Load(config, allPackages...)
|
s.packageList, err = packages.Load(config, allPackages...)
|
||||||
s.log.Info("Loaded packages ", "len results", len(s.packageList), "error", err)
|
s.log.Info("Loaded modules ", "len results", len(s.packageList), "error", err)
|
||||||
|
|
||||||
|
|
||||||
|
// Now process the files in the aap source folder s.revelContainer.ImportPath + "/...",
|
||||||
|
err = utils.Walk(s.revelContainer.AppPath, s.processPath)
|
||||||
|
s.log.Info("Loaded apps and modules ", "len results", len(s.packageList), "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This callback is used to build the packages for the "app" package. This allows us to
|
||||||
|
// parse the source files without doing a full compile on them
|
||||||
|
// This callback only processes folders, so any files passed to this will return a nil
|
||||||
|
func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
s.log.Error("Error scanning app source:", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore files and folders not marked tmp (since those are generated)
|
||||||
|
if !info.IsDir() || info.Name() == "tmp" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Real work for processing the folder
|
||||||
|
pkgImportPath := s.revelContainer.ImportPath
|
||||||
|
appPath := s.revelContainer.BasePath
|
||||||
|
if appPath != path {
|
||||||
|
pkgImportPath = s.revelContainer.ImportPath + "/" + filepath.ToSlash(path[len(appPath)+1:])
|
||||||
|
}
|
||||||
|
// Parse files within the path.
|
||||||
|
var pkgMap map[string]*ast.Package
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
pkgMap, err = parser.ParseDir(
|
||||||
|
fset,
|
||||||
|
path,
|
||||||
|
func(f os.FileInfo) bool {
|
||||||
|
return !f.IsDir() && !strings.HasPrefix(f.Name(), ".") && strings.HasSuffix(f.Name(), ".go")
|
||||||
|
},
|
||||||
|
0)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if errList, ok := err.(scanner.ErrorList); ok {
|
||||||
|
var pos = errList[0].Pos
|
||||||
|
newError := &utils.SourceError{
|
||||||
|
SourceType: ".go source",
|
||||||
|
Title: "Go Compilation Error",
|
||||||
|
Path: pos.Filename,
|
||||||
|
Description: errList[0].Msg,
|
||||||
|
Line: pos.Line,
|
||||||
|
Column: pos.Column,
|
||||||
|
SourceLines: utils.MustReadLines(pos.Filename),
|
||||||
|
}
|
||||||
|
|
||||||
|
errorLink := s.revelContainer.Config.StringDefault("error.link", "")
|
||||||
|
if errorLink != "" {
|
||||||
|
newError.SetLink(errorLink)
|
||||||
|
}
|
||||||
|
return newError
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is exception, err already checked above. Here just a print
|
||||||
|
ast.Print(nil, err)
|
||||||
|
s.log.Fatal("Failed to parse dir", "error", err)
|
||||||
|
}
|
||||||
|
// Skip "main" packages.
|
||||||
|
delete(pkgMap, "main")
|
||||||
|
|
||||||
|
// Ignore packages that end with _test
|
||||||
|
// These cannot be included in source code that is not generated specifically as a test
|
||||||
|
for i := range pkgMap {
|
||||||
|
if len(i) > 6 {
|
||||||
|
if string(i[len(i)-5:]) == "_test" {
|
||||||
|
delete(pkgMap, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no code in this directory, skip it.
|
||||||
|
if len(pkgMap) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// There should be only one package in this directory.
|
||||||
|
if len(pkgMap) > 1 {
|
||||||
|
for i := range pkgMap {
|
||||||
|
println("Found package ", i)
|
||||||
|
}
|
||||||
|
utils.Logger.Fatal("Most unexpected! Multiple packages in a single directory:", "packages", pkgMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point there is only one package in the pkgs map,
|
||||||
|
p := &packages.Package{}
|
||||||
|
p.PkgPath = pkgImportPath
|
||||||
|
p.Fset = fset
|
||||||
|
for _, pkg := range pkgMap {
|
||||||
|
p.Name = pkg.Name
|
||||||
|
s.log.Info("Found package","pkg.Name", pkg.Name,"p.Name", p.PkgPath)
|
||||||
|
for filename,astFile := range pkg.Files {
|
||||||
|
p.Syntax = append(p.Syntax,astFile)
|
||||||
|
p.GoFiles = append(p.GoFiles,filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.packageList = append(s.packageList, p)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is used to populate a map so that we can lookup controller embedded types in order to determine
|
||||||
|
// if a Struct inherits from from revel.Controller
|
||||||
func (s *SourceProcessor) addImportMap() (err error) {
|
func (s *SourceProcessor) addImportMap() (err error) {
|
||||||
s.importMap = map[string]string{}
|
s.importMap = map[string]string{}
|
||||||
s.packageMap = map[string]string{}
|
s.packageMap = map[string]string{}
|
||||||
@@ -113,41 +226,11 @@ func (s *SourceProcessor) addImportMap() (err error) {
|
|||||||
if len(p.Errors) > 0 {
|
if len(p.Errors) > 0 {
|
||||||
// Generate a compile error
|
// Generate a compile error
|
||||||
for _, e := range p.Errors {
|
for _, e := range p.Errors {
|
||||||
if !strings.Contains(e.Msg, "fsnotify") {
|
s.log.Info("While reading packages encountered import error ignoring ", "PkgPath", p.PkgPath, "error", e)
|
||||||
err = utils.NewCompileError("", "", e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, tree := range p.Syntax {
|
for _, tree := range p.Syntax {
|
||||||
for _, decl := range tree.Decls {
|
s.importMap[tree.Name.Name] = p.PkgPath
|
||||||
genDecl, ok := decl.(*ast.GenDecl)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if genDecl.Tok == token.IMPORT {
|
|
||||||
for _, spec := range genDecl.Specs {
|
|
||||||
importSpec := spec.(*ast.ImportSpec)
|
|
||||||
//fmt.Printf("*** import specification %#v\n", importSpec)
|
|
||||||
var pkgAlias string
|
|
||||||
if importSpec.Name != nil {
|
|
||||||
pkgAlias = importSpec.Name.Name
|
|
||||||
if pkgAlias == "_" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
|
|
||||||
fullPath := quotedPath[1 : len(quotedPath) - 1] // Remove the quotes
|
|
||||||
if pkgAlias == "" {
|
|
||||||
pkgAlias = fullPath
|
|
||||||
if index := strings.LastIndex(pkgAlias, "/"); index > 0 {
|
|
||||||
pkgAlias = pkgAlias[index + 1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.importMap[pkgAlias] = fullPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -165,53 +248,3 @@ func (s *SourceProcessor) addSourceInfo() (err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add imports to the map from the source dir
|
|
||||||
//func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
|
|
||||||
// genDecl, ok := decl.(*ast.GenDecl)
|
|
||||||
// if !ok {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if genDecl.Tok != token.IMPORT {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for _, spec := range genDecl.Specs {
|
|
||||||
// importSpec := spec.(*ast.ImportSpec)
|
|
||||||
// var pkgAlias string
|
|
||||||
// if importSpec.Name != nil {
|
|
||||||
// pkgAlias = importSpec.Name.Name
|
|
||||||
// if pkgAlias == "_" {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
|
|
||||||
// fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes
|
|
||||||
//
|
|
||||||
// // If the package was not aliased (common case), we have to import it
|
|
||||||
// // to see what the package name is.
|
|
||||||
// // TODO: Can improve performance here a lot:
|
|
||||||
// // 1. Do not import everything over and over again. Keep a cache.
|
|
||||||
// // 2. Exempt the standard library; their directories always match the package name.
|
|
||||||
// // 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly
|
|
||||||
// if pkgAlias == "" {
|
|
||||||
//
|
|
||||||
// utils.Logger.Debug("Reading from build", "path", fullPath, "srcPath", srcDir, "gopath", build.Default.GOPATH)
|
|
||||||
// pkg, err := build.Import(fullPath, srcDir, 0)
|
|
||||||
// if err != nil {
|
|
||||||
// // We expect this to happen for apps using reverse routing (since we
|
|
||||||
// // have not yet generated the routes). Don't log that.
|
|
||||||
// if !strings.HasSuffix(fullPath, "/app/routes") {
|
|
||||||
// utils.Logger.Warn("Could not find import:", "path", fullPath, "srcPath", srcDir, "error", err)
|
|
||||||
// }
|
|
||||||
// continue
|
|
||||||
// } else {
|
|
||||||
// utils.Logger.Debug("Found package in dir", "dir", pkg.Dir, "name", pkg.ImportPath)
|
|
||||||
// }
|
|
||||||
// pkgAlias = pkg.Name
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// imports[pkgAlias] = fullPath
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
14
revel/new.go
14
revel/new.go
@@ -72,7 +72,7 @@ func newApp(c *model.CommandConfig) (err error) {
|
|||||||
// Check for an existing folder so we don't clobber it
|
// Check for an existing folder so we don't clobber it
|
||||||
_, err = build.Import(c.ImportPath, "", build.FindOnly)
|
_, err = build.Import(c.ImportPath, "", build.FindOnly)
|
||||||
if err == nil || !utils.Empty(c.AppPath) {
|
if err == nil || !utils.Empty(c.AppPath) {
|
||||||
return utils.NewBuildError("Abort: Import path already exists.", "path", c.ImportPath)
|
return utils.NewBuildError("Abort: Import path already exists.", "path", c.ImportPath, "apppath", c.AppPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// checking and setting skeleton
|
// checking and setting skeleton
|
||||||
@@ -112,6 +112,10 @@ func newApp(c *model.CommandConfig) (err error) {
|
|||||||
fmt.Fprintln(os.Stdout, "Your application has been created in:\n ", c.AppPath)
|
fmt.Fprintln(os.Stdout, "Your application has been created in:\n ", c.AppPath)
|
||||||
// Check to see if it should be run right off
|
// Check to see if it should be run right off
|
||||||
if c.New.Run {
|
if c.New.Run {
|
||||||
|
// Need to prep the run command
|
||||||
|
c.Run.ImportPath = c.ImportPath
|
||||||
|
updateRunConfig(c,nil)
|
||||||
|
c.UpdateImportPath()
|
||||||
runApp(c)
|
runApp(c)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a ", c.ImportPath)
|
fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a ", c.ImportPath)
|
||||||
@@ -203,13 +207,13 @@ func setApplicationPath(c *model.CommandConfig) (err error) {
|
|||||||
// revel/revel#1014 validate relative path, we cannot use built-in functions
|
// revel/revel#1014 validate relative path, we cannot use built-in functions
|
||||||
// since Go import path is valid relative path too.
|
// since Go import path is valid relative path too.
|
||||||
// so check basic part of the path, which is "."
|
// so check basic part of the path, which is "."
|
||||||
if filepath.IsAbs(c.ImportPath) || strings.HasPrefix(c.ImportPath, ".") {
|
|
||||||
utils.Logger.Fatalf("Abort: '%s' looks like a directory. Please provide a Go import path instead.",
|
|
||||||
c.ImportPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are running a vendored version of Revel we do not need to check for it.
|
// If we are running a vendored version of Revel we do not need to check for it.
|
||||||
if !c.Vendored {
|
if !c.Vendored {
|
||||||
|
if filepath.IsAbs(c.ImportPath) || strings.HasPrefix(c.ImportPath, ".") {
|
||||||
|
utils.Logger.Fatalf("Abort: '%s' looks like a directory. Please provide a Go import path instead.",
|
||||||
|
c.ImportPath)
|
||||||
|
}
|
||||||
_, err = build.Import(model.RevelImportPath, "", build.FindOnly)
|
_, err = build.Import(model.RevelImportPath, "", build.FindOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//// Go get the revel project
|
//// Go get the revel project
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ import (
|
|||||||
"github.com/revel/cmd/harness"
|
"github.com/revel/cmd/harness"
|
||||||
"github.com/revel/cmd/model"
|
"github.com/revel/cmd/model"
|
||||||
"github.com/revel/cmd/utils"
|
"github.com/revel/cmd/utils"
|
||||||
"go/build"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdRun = &Command{
|
var cmdRun = &Command{
|
||||||
@@ -116,10 +114,7 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool {
|
|||||||
|
|
||||||
// Returns true if this is an absolute path or a relative gopath
|
// Returns true if this is an absolute path or a relative gopath
|
||||||
func runIsImportPath(pathToCheck string) bool {
|
func runIsImportPath(pathToCheck string) bool {
|
||||||
if _, err := build.Import(pathToCheck, "", build.FindOnly); err == nil {
|
return utils.DirExists(pathToCheck)
|
||||||
return true
|
|
||||||
}
|
|
||||||
return filepath.IsAbs(pathToCheck)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called to run the app
|
// Called to run the app
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ func TestVersion(t *testing.T) {
|
|||||||
a.Nil(main.Commands[model.VERSION].RunWith(c), "Failed to run version-test")
|
a.Nil(main.Commands[model.VERSION].RunWith(c), "Failed to run version-test")
|
||||||
})
|
})
|
||||||
if !t.Failed() {
|
if !t.Failed() {
|
||||||
if err := os.RemoveAll(gopath); err != nil {
|
if err := os.RemoveAll(gopath); err != nil && err!=os.ErrNotExist {
|
||||||
a.Fail("Failed to remove test path")
|
a.Fail("Failed to remove test path",err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,7 +203,8 @@ func Walk(root string, walkFn filepath.WalkFunc) error {
|
|||||||
return fsWalk(root, root, walkFn)
|
return fsWalk(root, root, walkFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk the tree using the function
|
// Walk the path tree using the function
|
||||||
|
// Every file found will call the function
|
||||||
func fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error {
|
func fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error {
|
||||||
fsWalkFunc := func(path string, info os.FileInfo, err error) error {
|
fsWalkFunc := func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -308,9 +309,13 @@ func Exists(filename string) bool {
|
|||||||
// empty returns true if the given directory is empty.
|
// empty returns true if the given directory is empty.
|
||||||
// the directory must exist.
|
// the directory must exist.
|
||||||
func Empty(dirname string) bool {
|
func Empty(dirname string) bool {
|
||||||
|
if !DirExists(dirname) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
dir, err := os.Open(dirname)
|
dir, err := os.Open(dirname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Logger.Infof("error opening directory: %s", err)
|
Logger.Infof("error opening directory: %s", err)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = dir.Close()
|
_ = dir.Close()
|
||||||
@@ -322,8 +327,8 @@ func Empty(dirname string) bool {
|
|||||||
// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory
|
// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory
|
||||||
func FindSrcPaths(appPath string, packageList []string, packageResolver func(pkgName string) error) (sourcePathsmap map[string]string, err error) {
|
func FindSrcPaths(appPath string, packageList []string, packageResolver func(pkgName string) error) (sourcePathsmap map[string]string, err error) {
|
||||||
sourcePathsmap, missingList, err := findSrcPaths(appPath, packageList)
|
sourcePathsmap, missingList, err := findSrcPaths(appPath, packageList)
|
||||||
if err != nil && packageResolver != nil || len(missingList)>0 {
|
if err != nil && packageResolver != nil || len(missingList) > 0 {
|
||||||
Logger.Info("Failed to find package, attempting to call resolver for missing packages","missing packages",missingList)
|
Logger.Info("Failed to find package, attempting to call resolver for missing packages", "missing packages", missingList)
|
||||||
for _, item := range missingList {
|
for _, item := range missingList {
|
||||||
if err = packageResolver(item); err != nil {
|
if err = packageResolver(item); err != nil {
|
||||||
return
|
return
|
||||||
@@ -352,25 +357,25 @@ func findSrcPaths(appPath string, packagesList []string) (sourcePathsmap map[str
|
|||||||
Dir:appPath,
|
Dir:appPath,
|
||||||
}
|
}
|
||||||
sourcePathsmap = map[string]string{}
|
sourcePathsmap = map[string]string{}
|
||||||
Logger.Infof("Environment path %s root %s config env %s", os.Getenv("GOPATH"), os.Getenv("GOROOT"),config.Env)
|
Logger.Infof("Environment path %s root %s config env %s", os.Getenv("GOPATH"), os.Getenv("GOROOT"), config.Env)
|
||||||
|
|
||||||
pkgs, err := packages.Load(config, packagesList...)
|
pkgs, err := packages.Load(config, packagesList...)
|
||||||
Logger.Infof("Environment path %s root %s config env %s", os.Getenv("GOPATH"), os.Getenv("GOROOT"),config.Env)
|
Logger.Infof("Environment path %s root %s config env %s", os.Getenv("GOPATH"), os.Getenv("GOROOT"), config.Env)
|
||||||
Logger.Info("Loaded packages ", "len results", len(pkgs), "error", err, "basedir", appPath)
|
Logger.Info("Loaded packages ", "len results", len(pkgs), "error", err, "basedir", appPath)
|
||||||
for _, packageName := range packagesList {
|
for _, packageName := range packagesList {
|
||||||
found := false
|
found := false
|
||||||
log := Logger.New("seeking", packageName)
|
log := Logger.New("seeking", packageName)
|
||||||
for _, pck := range pkgs {
|
for _, pck := range pkgs {
|
||||||
log.Info("Found package", "package", pck.ID)
|
log.Info("Found package", "package", pck.ID)
|
||||||
if pck.ID == packageName {
|
if pck.ID == packageName {
|
||||||
if pck.Errors != nil && len(pck.Errors) > 0 {
|
if pck.Errors != nil && len(pck.Errors) > 0 {
|
||||||
log.Info("Error ", "count", len(pck.Errors), "App Import Path", pck.ID, "errors", pck.Errors)
|
log.Error("Error ", "count", len(pck.Errors), "App Import Path", pck.ID, "filesystem path", pck.PkgPath, "errors", pck.Errors)
|
||||||
continue
|
// continue
|
||||||
|
|
||||||
}
|
}
|
||||||
//a,_ := pck.MarshalJSON()
|
//a,_ := pck.MarshalJSON()
|
||||||
log.Info("Found ", "count", len(pck.GoFiles), "App Import Path", pck.ID, "apppath", appPath)
|
log.Info("Found ", "count", len(pck.GoFiles), "App Import Path", pck.ID, "apppath", appPath)
|
||||||
if len(pck.GoFiles)>0 {
|
if len(pck.GoFiles) > 0 {
|
||||||
sourcePathsmap[packageName] = filepath.Dir(pck.GoFiles[0])
|
sourcePathsmap[packageName] = filepath.Dir(pck.GoFiles[0])
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ type DiscerningListener interface {
|
|||||||
// Watcher allows listeners to register to be notified of changes under a given
|
// Watcher allows listeners to register to be notified of changes under a given
|
||||||
// directory.
|
// directory.
|
||||||
type Watcher struct {
|
type Watcher struct {
|
||||||
// Parallel arrays of watcher/listener pairs.
|
// Parallel arrays of watcher/listener pairs.
|
||||||
watchers []*fsnotify.Watcher
|
watchers []*fsnotify.Watcher
|
||||||
listeners []Listener
|
listeners []Listener
|
||||||
forceRefresh bool
|
forceRefresh bool
|
||||||
@@ -42,8 +42,8 @@ type Watcher struct {
|
|||||||
lastError int
|
lastError int
|
||||||
notifyMutex sync.Mutex
|
notifyMutex sync.Mutex
|
||||||
paths *model.RevelContainer
|
paths *model.RevelContainer
|
||||||
refreshTimer *time.Timer // The timer to countdown the next refresh
|
refreshTimer *time.Timer // The timer to countdown the next refresh
|
||||||
timerMutex *sync.Mutex // A mutex to prevent concurrent updates
|
timerMutex *sync.Mutex // A mutex to prevent concurrent updates
|
||||||
refreshChannel chan *utils.SourceError
|
refreshChannel chan *utils.SourceError
|
||||||
refreshChannelCount int
|
refreshChannelCount int
|
||||||
refreshTimerMS time.Duration // The number of milliseconds between refreshing builds
|
refreshTimerMS time.Duration // The number of milliseconds between refreshing builds
|
||||||
@@ -52,10 +52,10 @@ type Watcher struct {
|
|||||||
// Creates a new watched based on the container
|
// Creates a new watched based on the container
|
||||||
func NewWatcher(paths *model.RevelContainer, eagerRefresh bool) *Watcher {
|
func NewWatcher(paths *model.RevelContainer, eagerRefresh bool) *Watcher {
|
||||||
return &Watcher{
|
return &Watcher{
|
||||||
forceRefresh: true,
|
forceRefresh: false,
|
||||||
lastError: -1,
|
lastError: -1,
|
||||||
paths: paths,
|
paths: paths,
|
||||||
refreshTimerMS: time.Duration(paths.Config.IntDefault("watch.rebuild.delay", 10)),
|
refreshTimerMS: time.Duration(paths.Config.IntDefault("watch.rebuild.delay", 1000)),
|
||||||
eagerRefresh: eagerRefresh ||
|
eagerRefresh: eagerRefresh ||
|
||||||
paths.DevMode &&
|
paths.DevMode &&
|
||||||
paths.Config.BoolDefault("watch", true) &&
|
paths.Config.BoolDefault("watch", true) &&
|
||||||
@@ -85,7 +85,7 @@ func (w *Watcher) Listen(listener Listener, roots ...string) {
|
|||||||
for _, p := range roots {
|
for _, p := range roots {
|
||||||
// is the directory / file a symlink?
|
// is the directory / file a symlink?
|
||||||
f, err := os.Lstat(p)
|
f, err := os.Lstat(p)
|
||||||
if err == nil && f.Mode()&os.ModeSymlink == os.ModeSymlink {
|
if err == nil && f.Mode() & os.ModeSymlink == os.ModeSymlink {
|
||||||
var realPath string
|
var realPath string
|
||||||
realPath, err = filepath.EvalSymlinks(p)
|
realPath, err = filepath.EvalSymlinks(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -200,12 +200,13 @@ func (w *Watcher) Notify() *utils.SourceError {
|
|||||||
case <-watcher.Errors:
|
case <-watcher.Errors:
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
// No events left to pull
|
// No events left to pull
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.Logger.Info("Watcher:Notify refresh state", "Current Index", i, " last error index", w.lastError)
|
utils.Logger.Info("Watcher:Notify refresh state", "Current Index", i, " last error index", w.lastError,
|
||||||
|
"force", w.forceRefresh, "refresh", refresh, "lastError", w.lastError == i)
|
||||||
if w.forceRefresh || refresh || w.lastError == i {
|
if w.forceRefresh || refresh || w.lastError == i {
|
||||||
var err *utils.SourceError
|
var err *utils.SourceError
|
||||||
if w.serial {
|
if w.serial {
|
||||||
@@ -285,22 +286,10 @@ func (w *Watcher) rebuildRequired(ev fsnotify.Event, listener Listener) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dl, ok := listener.(DiscerningListener); ok {
|
if dl, ok := listener.(DiscerningListener); ok {
|
||||||
if !dl.WatchFile(ev.Name) || ev.Op&fsnotify.Chmod == fsnotify.Chmod {
|
if !dl.WatchFile(ev.Name) || ev.Op & fsnotify.Chmod == fsnotify.Chmod {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
var WatchFilter = func(c *Controller, fc []Filter) {
|
|
||||||
if MainWatcher != nil {
|
|
||||||
err := MainWatcher.Notify()
|
|
||||||
if err != nil {
|
|
||||||
c.Result = c.RenderError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fc[0](c, fc[1:])
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
Reference in New Issue
Block a user