Browse Source

Refactor!

create sub packages
delete unused code
delete code from not use command cmdRouter,cmdTest, cmdRundocs
make command plugins
check with gosimple,staticcheck,go vet,unused,unconvert
tags/v1.8.3
Sergey Lanzman 2 years ago
parent
commit
c538bfbc8f
47 changed files with 1838 additions and 2467 deletions
  1. 0
    280
      autorouter.go
  2. 0
    9
      autorouter_test.go
  3. 0
    258
      bee.go
  4. 102
    0
      cmd/bee.go
  5. 41
    71
      cmd/commands/api/apiapp.go
  6. 24
    19
      cmd/commands/bale/bale.go
  7. 16
    10
      cmd/commands/beefix/fix.go
  8. 94
    0
      cmd/commands/command.go
  9. 32
    24
      cmd/commands/dockerize/dockerize.go
  10. 203
    0
      cmd/commands/generate/generate.go
  11. 119
    0
      cmd/commands/hprose/hprose.go
  12. 79
    91
      cmd/commands/migrate/migrate.go
  13. 80
    70
      cmd/commands/new/new.go
  14. 36
    59
      cmd/commands/pack/pack.go
  15. 88
    0
      cmd/commands/run/docs.go
  16. 7
    6
      cmd/commands/run/reload.go
  17. 49
    46
      cmd/commands/run/run.go
  18. 32
    28
      cmd/commands/run/watch.go
  19. 18
    7
      cmd/commands/version/banner.go
  20. 33
    23
      cmd/commands/version/version.go
  21. 0
    261
      code.go
  22. 25
    26
      config/conf.go
  23. 0
    200
      g.go
  24. 0
    48
      g_scaffold.go
  25. 23
    0
      generate/g.go
  26. 74
    71
      generate/g_appcode.go
  27. 14
    10
      generate/g_controllers.go
  28. 266
    21
      generate/g_hproseappcode.go
  29. 31
    27
      generate/g_migration.go
  30. 15
    11
      generate/g_model.go
  31. 50
    0
      generate/g_scaffold.go
  32. 17
    13
      generate/g_views.go
  33. 25
    35
      generate/swaggergen/g_docs.go
  34. 0
    369
      hproseapp.go
  35. 20
    20
      logger/colors/color.go
  36. 1
    1
      logger/colors/colorwriter.go
  37. 1
    1
      logger/colors/colorwriter_windows.go
  38. 41
    18
      logger/logger.go
  39. 59
    0
      main.go
  40. 0
    155
      rundocs.go
  41. 0
    102
      test.go
  42. 0
    28
      testdata/router/router.go
  43. 14
    0
      utils/doc_value.go
  44. 14
    0
      utils/list_opts.go
  45. 15
    0
      utils/str_flag.go
  46. 79
    48
      utils/utils.go
  47. 1
    1
      vendor/github.com/smartystreets/assertions/internal/oglematchers/transform_description.go

+ 0
- 280
autorouter.go View File

@@ -1,280 +0,0 @@
1
-// Copyright 2013 bee authors
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
-// not use this file except in compliance with the License. You may obtain
5
-// a copy of the License at
6
-//
7
-//     http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
-// License for the specific language governing permissions and limitations
13
-// under the License.
14
-
15
-package main
16
-
17
-import (
18
-	"bytes"
19
-	"errors"
20
-	"fmt"
21
-	"go/ast"
22
-	gobuild "go/build"
23
-	"go/doc"
24
-	"go/parser"
25
-	"go/token"
26
-	"io"
27
-	"io/ioutil"
28
-	"os"
29
-	"path"
30
-	"runtime"
31
-	"strings"
32
-	"time"
33
-)
34
-
35
-var cmdRouter = &Command{
36
-	UsageLine: "router",
37
-	Short:     "auto-generate routers for the app controllers",
38
-	Long: `
39
-  
40
-`,
41
-}
42
-
43
-func init() {
44
-	cmdRouter.Run = autoRouter
45
-}
46
-
47
-func autoRouter(cmd *Command, args []string) int {
48
-	fmt.Println("[INFO] Starting auto-generating routers...")
49
-	return 0
50
-}
51
-
52
-// getControllerInfo returns controllers that embeded "beego.controller"
53
-// and their methods of package in given path.
54
-func getControllerInfo(path string) (map[string][]string, error) {
55
-	now := time.Now()
56
-	path = strings.TrimSuffix(path, "/")
57
-	dir, err := os.Open(path)
58
-	if err != nil {
59
-		return nil, err
60
-	}
61
-
62
-	fis, err := dir.Readdir(0)
63
-	if err != nil {
64
-		return nil, err
65
-	}
66
-
67
-	files := make([]*source, 0, len(fis))
68
-	for _, fi := range fis {
69
-		// Only load Go files
70
-		if strings.HasSuffix(fi.Name(), ".go") {
71
-			f, err := os.Open(path + "/" + fi.Name())
72
-			if err != nil {
73
-				return nil, err
74
-			}
75
-
76
-			p := make([]byte, fi.Size())
77
-			_, err = f.Read(p)
78
-			if err != nil {
79
-				return nil, err
80
-			}
81
-
82
-			f.Close()
83
-			files = append(files, &source{
84
-				name: path + "/" + fi.Name(),
85
-				data: p,
86
-			})
87
-		}
88
-	}
89
-
90
-	rw := &routerWalker{
91
-		pdoc: &Package{
92
-			ImportPath: path,
93
-		},
94
-	}
95
-
96
-	cm := make(map[string][]string)
97
-	pdoc, err := rw.build(files)
98
-	for _, t := range pdoc.Types {
99
-		// Check if embeded "beego.Controller".
100
-		if strings.Index(t.Decl, "beego.Controller") > -1 {
101
-			for _, f := range t.Methods {
102
-				cm[t.Name] = append(cm[t.Name], f.Name)
103
-			}
104
-		}
105
-	}
106
-	fmt.Println(time.Since(now))
107
-	return cm, nil
108
-}
109
-
110
-// source represents a source code file.
111
-type source struct {
112
-	name string
113
-	data []byte
114
-}
115
-
116
-func (s *source) Name() string       { return s.name }
117
-func (s *source) Size() int64        { return int64(len(s.data)) }
118
-func (s *source) Mode() os.FileMode  { return 0 }
119
-func (s *source) ModTime() time.Time { return time.Time{} }
120
-func (s *source) IsDir() bool        { return false }
121
-func (s *source) Sys() interface{}   { return nil }
122
-
123
-// routerWalker holds the state used when building the documentation.
124
-type routerWalker struct {
125
-	pdoc *Package
126
-	srcs map[string]*source // Source files
127
-	fset *token.FileSet
128
-	buf  []byte // scratch space for printNode method
129
-}
130
-
131
-// Package represents full information and documentation for a package.
132
-type Package struct {
133
-	ImportPath string
134
-	Types      []*Type // Top-level declarations
135
-}
136
-
137
-// Type represents structs and interfaces.
138
-type Type struct {
139
-	Name    string // Type name
140
-	Decl    string
141
-	Methods []*Func // Exported methods
142
-}
143
-
144
-// Func represents functions
145
-type Func struct {
146
-	Name string
147
-}
148
-
149
-// build generates data from source files.
150
-func (w *routerWalker) build(srcs []*source) (*Package, error) {
151
-	// Add source files to walker, I skipped references here
152
-	w.srcs = make(map[string]*source)
153
-	for _, src := range srcs {
154
-		w.srcs[src.name] = src
155
-	}
156
-
157
-	w.fset = token.NewFileSet()
158
-
159
-	// Find the package and associated files
160
-	ctxt := gobuild.Context{
161
-		GOOS:          runtime.GOOS,
162
-		GOARCH:        runtime.GOARCH,
163
-		CgoEnabled:    true,
164
-		JoinPath:      path.Join,
165
-		IsAbsPath:     path.IsAbs,
166
-		SplitPathList: func(list string) []string { return strings.Split(list, ":") },
167
-		IsDir:         func(path string) bool { panic("unexpected") },
168
-		HasSubdir:     func(root, dir string) (rel string, ok bool) { panic("unexpected") },
169
-		ReadDir:       func(dir string) (fi []os.FileInfo, err error) { return w.readDir(dir) },
170
-		OpenFile:      func(path string) (r io.ReadCloser, err error) { return w.openFile(path) },
171
-		Compiler:      "gc",
172
-	}
173
-
174
-	bpkg, err := ctxt.ImportDir(w.pdoc.ImportPath, 0)
175
-	// Continue if there are no Go source files; we still want the directory info
176
-	_, nogo := err.(*gobuild.NoGoError)
177
-	if err != nil {
178
-		if nogo {
179
-			err = nil
180
-		} else {
181
-			return nil, errors.New("routerWalker.build -> " + err.Error())
182
-		}
183
-	}
184
-
185
-	// Parse the Go files
186
-	files := make(map[string]*ast.File)
187
-	for _, name := range append(bpkg.GoFiles, bpkg.CgoFiles...) {
188
-		file, err := parser.ParseFile(w.fset, name, w.srcs[name].data, parser.ParseComments)
189
-		if err != nil {
190
-			return nil, errors.New("routerWalker.build -> parse go files: " + err.Error())
191
-		}
192
-		files[name] = file
193
-	}
194
-
195
-	apkg, _ := ast.NewPackage(w.fset, files, simpleImporter, nil)
196
-
197
-	mode := doc.Mode(0)
198
-	if w.pdoc.ImportPath == "builtin" {
199
-		mode |= doc.AllDecls
200
-	}
201
-
202
-	pdoc := doc.New(apkg, w.pdoc.ImportPath, mode)
203
-
204
-	w.pdoc.Types = w.types(pdoc.Types)
205
-
206
-	return w.pdoc, err
207
-}
208
-
209
-func (w *routerWalker) funcs(fdocs []*doc.Func) []*Func {
210
-	var result []*Func
211
-	for _, d := range fdocs {
212
-		result = append(result, &Func{
213
-			Name: d.Name,
214
-		})
215
-	}
216
-	return result
217
-}
218
-
219
-func (w *routerWalker) types(tdocs []*doc.Type) []*Type {
220
-	var result []*Type
221
-	for _, d := range tdocs {
222
-		result = append(result, &Type{
223
-			Decl:    w.printDecl(d.Decl),
224
-			Name:    d.Name,
225
-			Methods: w.funcs(d.Methods),
226
-		})
227
-	}
228
-	return result
229
-}
230
-
231
-func (w *routerWalker) printDecl(decl ast.Node) string {
232
-	var d Code
233
-	d, w.buf = printDecl(decl, w.fset, w.buf)
234
-	return d.Text
235
-}
236
-
237
-func (w *routerWalker) readDir(dir string) ([]os.FileInfo, error) {
238
-	if dir != w.pdoc.ImportPath {
239
-		panic("unexpected")
240
-	}
241
-	fis := make([]os.FileInfo, 0, len(w.srcs))
242
-	for _, src := range w.srcs {
243
-		fis = append(fis, src)
244
-	}
245
-	return fis, nil
246
-}
247
-
248
-func (w *routerWalker) openFile(path string) (io.ReadCloser, error) {
249
-	if strings.HasPrefix(path, w.pdoc.ImportPath+"/") {
250
-		if src, ok := w.srcs[path[len(w.pdoc.ImportPath)+1:]]; ok {
251
-			return ioutil.NopCloser(bytes.NewReader(src.data)), nil
252
-		}
253
-	}
254
-	panic("unexpected")
255
-}
256
-
257
-func simpleImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
258
-	pkg := imports[path]
259
-	if pkg == nil {
260
-		// Guess the package name without importing it. Start with the last
261
-		// element of the path.
262
-		name := path[strings.LastIndex(path, "/")+1:]
263
-
264
-		// Trim commonly used prefixes and suffixes containing illegal name
265
-		// runes.
266
-		name = strings.TrimSuffix(name, ".go")
267
-		name = strings.TrimSuffix(name, "-go")
268
-		name = strings.TrimPrefix(name, "go.")
269
-		name = strings.TrimPrefix(name, "go-")
270
-		name = strings.TrimPrefix(name, "biogo.")
271
-
272
-		// It's also common for the last element of the path to contain an
273
-		// extra "go" prefix, but not always.
274
-		// TODO: examine unresolved ids to detect when trimming the "go" prefix is appropriate.
275
-		pkg = ast.NewObj(ast.Pkg, name)
276
-		pkg.Data = ast.NewScope(nil)
277
-		imports[path] = pkg
278
-	}
279
-	return pkg, nil
280
-}

+ 0
- 9
autorouter_test.go View File

@@ -1,9 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"testing"
5
-)
6
-
7
-func TestGetControllerInfo(t *testing.T) {
8
-	getControllerInfo("testdata/router/")
9
-}

+ 0
- 258
bee.go View File

@@ -1,258 +0,0 @@
1
-// Copyright 2013 bee authors
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
-// not use this file except in compliance with the License. You may obtain
5
-// a copy of the License at
6
-//
7
-//     http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
-// License for the specific language governing permissions and limitations
13
-// under the License.
14
-
15
-// Bee is a tool for developing applications based on beego framework.
16
-package main
17
-
18
-import (
19
-	"flag"
20
-	"fmt"
21
-	"io"
22
-	"log"
23
-	"os"
24
-	"strings"
25
-	"text/template"
26
-)
27
-
28
-const version = "1.8.0"
29
-
30
-// Command is the unit of execution
31
-type Command struct {
32
-	// Run runs the command.
33
-	// The args are the arguments after the command name.
34
-	Run func(cmd *Command, args []string) int
35
-
36
-	// PreRun performs an operation before running the command
37
-	PreRun func(cmd *Command, args []string)
38
-
39
-	// UsageLine is the one-line usage message.
40
-	// The first word in the line is taken to be the command name.
41
-	UsageLine string
42
-
43
-	// Short is the short description shown in the 'go help' output.
44
-	Short string
45
-
46
-	// Long is the long message shown in the 'go help <this-command>' output.
47
-	Long string
48
-
49
-	// Flag is a set of flags specific to this command.
50
-	Flag flag.FlagSet
51
-
52
-	// CustomFlags indicates that the command will do its own
53
-	// flag parsing.
54
-	CustomFlags bool
55
-
56
-	// output out writer if set in SetOutput(w)
57
-	output *io.Writer
58
-}
59
-
60
-// Name returns the command's name: the first word in the usage line.
61
-func (c *Command) Name() string {
62
-	name := c.UsageLine
63
-	i := strings.Index(name, " ")
64
-	if i >= 0 {
65
-		name = name[:i]
66
-	}
67
-	return name
68
-}
69
-
70
-// SetOutput sets the destination for usage and error messages.
71
-// If output is nil, os.Stderr is used.
72
-func (c *Command) SetOutput(output io.Writer) {
73
-	c.output = &output
74
-}
75
-
76
-// Out returns the out writer of the current command.
77
-// If cmd.output is nil, os.Stderr is used.
78
-func (c *Command) Out() io.Writer {
79
-	if c.output != nil {
80
-		return *c.output
81
-	}
82
-	return NewColorWriter(os.Stderr)
83
-}
84
-
85
-// Usage puts out the usage for the command.
86
-func (c *Command) Usage() {
87
-	tmpl(cmdUsage, c)
88
-	os.Exit(2)
89
-}
90
-
91
-// Runnable reports whether the command can be run; otherwise
92
-// it is a documentation pseudo-command such as import path.
93
-func (c *Command) Runnable() bool {
94
-	return c.Run != nil
95
-}
96
-
97
-func (c *Command) Options() map[string]string {
98
-	options := make(map[string]string)
99
-	c.Flag.VisitAll(func(f *flag.Flag) {
100
-		defaultVal := f.DefValue
101
-		if len(defaultVal) > 0 {
102
-			options[f.Name+"="+defaultVal] = f.Usage
103
-		} else {
104
-			options[f.Name] = f.Usage
105
-		}
106
-	})
107
-	return options
108
-}
109
-
110
-var availableCommands = []*Command{
111
-	cmdNew,
112
-	cmdRun,
113
-	cmdPack,
114
-	cmdApiapp,
115
-	cmdHproseapp,
116
-	//cmdRouter,
117
-	//cmdTest,
118
-	cmdBale,
119
-	cmdVersion,
120
-	cmdGenerate,
121
-	//cmdRundocs,
122
-	cmdMigrate,
123
-	cmdFix,
124
-	cmdDockerize,
125
-}
126
-
127
-var logger = GetBeeLogger(os.Stdout)
128
-
129
-func main() {
130
-	currentpath, _ := os.Getwd()
131
-
132
-	flag.Usage = usage
133
-	flag.Parse()
134
-	log.SetFlags(0)
135
-
136
-	args := flag.Args()
137
-
138
-	if len(args) < 1 {
139
-		usage()
140
-	}
141
-
142
-	if args[0] == "help" {
143
-		help(args[1:])
144
-		return
145
-	}
146
-
147
-	for _, cmd := range availableCommands {
148
-		if cmd.Name() == args[0] && cmd.Run != nil {
149
-			cmd.Flag.Usage = func() { cmd.Usage() }
150
-			if cmd.CustomFlags {
151
-				args = args[1:]
152
-			} else {
153
-				cmd.Flag.Parse(args[1:])
154
-				args = cmd.Flag.Args()
155
-			}
156
-
157
-			if cmd.PreRun != nil {
158
-				cmd.PreRun(cmd, args)
159
-			}
160
-
161
-			// Check if current directory is inside the GOPATH,
162
-			// if so parse the packages inside it.
163
-			if strings.Contains(currentpath, GetGOPATHs()[0]+"/src") && isGenerateDocs(cmd.Name(), args) {
164
-				parsePackagesFromDir(currentpath)
165
-			}
166
-
167
-			os.Exit(cmd.Run(cmd, args))
168
-			return
169
-		}
170
-	}
171
-
172
-	printErrorAndExit("Unknown subcommand")
173
-}
174
-
175
-func isGenerateDocs(name string, args []string) bool {
176
-	if name != "generate" {
177
-		return false
178
-	}
179
-	for _, a := range args {
180
-		if a == "docs" {
181
-			return true
182
-		}
183
-	}
184
-	return false
185
-}
186
-
187
-var usageTemplate = `Bee is a Fast and Flexible tool for managing your Beego Web Application.
188
-
189
-{{"USAGE" | headline}}
190
-    {{"bee command [arguments]" | bold}}
191
-
192
-{{"AVAILABLE COMMANDS" | headline}}
193
-{{range .}}{{if .Runnable}}
194
-    {{.Name | printf "%-11s" | bold}} {{.Short}}{{end}}{{end}}
195
-
196
-Use {{"bee help [command]" | bold}} for more information about a command.
197
-
198
-{{"ADDITIONAL HELP TOPICS" | headline}}
199
-{{range .}}{{if not .Runnable}}
200
-    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
201
-
202
-Use {{"bee help [topic]" | bold}} for more information about that topic.
203
-`
204
-
205
-var helpTemplate = `{{"USAGE" | headline}}
206
-  {{.UsageLine | printf "bee %s" | bold}}
207
-{{if .Options}}{{endline}}{{"OPTIONS" | headline}}{{range $k,$v := .Options}}
208
-  {{$k | printf "-%s" | bold}}
209
-      {{$v}}
210
-  {{end}}{{end}}
211
-{{"DESCRIPTION" | headline}}
212
-  {{tmpltostr .Long . | trim}}
213
-`
214
-
215
-var errorTemplate = `bee: %s.
216
-Use {{"bee help" | bold}} for more information.
217
-`
218
-
219
-var cmdUsage = `Use {{printf "bee help %s" .Name | bold}} for more information.{{endline}}`
220
-
221
-func usage() {
222
-	tmpl(usageTemplate, availableCommands)
223
-	os.Exit(2)
224
-}
225
-
226
-func tmpl(text string, data interface{}) {
227
-	output := NewColorWriter(os.Stderr)
228
-
229
-	t := template.New("usage").Funcs(BeeFuncMap())
230
-	template.Must(t.Parse(text))
231
-
232
-	err := t.Execute(output, data)
233
-	MustCheck(err)
234
-}
235
-
236
-func help(args []string) {
237
-	if len(args) == 0 {
238
-		usage()
239
-	}
240
-	if len(args) != 1 {
241
-		printErrorAndExit("Too many arguments")
242
-	}
243
-
244
-	arg := args[0]
245
-
246
-	for _, cmd := range availableCommands {
247
-		if cmd.Name() == arg {
248
-			tmpl(helpTemplate, cmd)
249
-			return
250
-		}
251
-	}
252
-	printErrorAndExit("Unknown help topic")
253
-}
254
-
255
-func printErrorAndExit(message string) {
256
-	tmpl(fmt.Sprintf(errorTemplate, message), nil)
257
-	os.Exit(2)
258
-}

+ 102
- 0
cmd/bee.go View File

@@ -0,0 +1,102 @@
1
+// Copyright 2013 bee authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+// Bee is a tool for developing applications based on beego framework.
16
+package cmd
17
+
18
+import (
19
+	"os"
20
+
21
+	"github.com/beego/bee/cmd/commands"
22
+	_ "github.com/beego/bee/cmd/commands/api"
23
+	_ "github.com/beego/bee/cmd/commands/bale"
24
+	_ "github.com/beego/bee/cmd/commands/beefix"
25
+	_ "github.com/beego/bee/cmd/commands/dockerize"
26
+	_ "github.com/beego/bee/cmd/commands/generate"
27
+	_ "github.com/beego/bee/cmd/commands/hprose"
28
+	_ "github.com/beego/bee/cmd/commands/migrate"
29
+	_ "github.com/beego/bee/cmd/commands/new"
30
+	_ "github.com/beego/bee/cmd/commands/pack"
31
+	_ "github.com/beego/bee/cmd/commands/run"
32
+	_ "github.com/beego/bee/cmd/commands/version"
33
+	"github.com/beego/bee/utils"
34
+)
35
+
36
+func IfGenerateDocs(name string, args []string) bool {
37
+	if name != "generate" {
38
+		return false
39
+	}
40
+	for _, a := range args {
41
+		if a == "docs" {
42
+			return true
43
+		}
44
+	}
45
+	return false
46
+}
47
+
48
+var usageTemplate = `Bee is a Fast and Flexible tool for managing your Beego Web Application.
49
+
50
+{{"USAGE" | headline}}
51
+    {{"bee command [arguments]" | bold}}
52
+
53
+{{"AVAILABLE COMMANDS" | headline}}
54
+{{range .}}{{if .Runnable}}
55
+    {{.Name | printf "%-11s" | bold}} {{.Short}}{{end}}{{end}}
56
+
57
+Use {{"bee help [command]" | bold}} for more information about a command.
58
+
59
+{{"ADDITIONAL HELP TOPICS" | headline}}
60
+{{range .}}{{if not .Runnable}}
61
+    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
62
+
63
+Use {{"bee help [topic]" | bold}} for more information about that topic.
64
+`
65
+
66
+var helpTemplate = `{{"USAGE" | headline}}
67
+  {{.UsageLine | printf "bee %s" | bold}}
68
+{{if .Options}}{{endline}}{{"OPTIONS" | headline}}{{range $k,$v := .Options}}
69
+  {{$k | printf "-%s" | bold}}
70
+      {{$v}}
71
+  {{end}}{{end}}
72
+{{"DESCRIPTION" | headline}}
73
+  {{tmpltostr .Long . | trim}}
74
+`
75
+
76
+var ErrorTemplate = `bee: %s.
77
+Use {{"bee help" | bold}} for more information.
78
+`
79
+
80
+func Usage() {
81
+	utils.Tmpl(usageTemplate, commands.AvailableCommands)
82
+	os.Exit(2)
83
+}
84
+
85
+func Help(args []string) {
86
+	if len(args) == 0 {
87
+		Usage()
88
+	}
89
+	if len(args) != 1 {
90
+		utils.PrintErrorAndExit("Too many arguments", ErrorTemplate)
91
+	}
92
+
93
+	arg := args[0]
94
+
95
+	for _, cmd := range commands.AvailableCommands {
96
+		if cmd.Name() == arg {
97
+			utils.Tmpl(helpTemplate, cmd)
98
+			return
99
+		}
100
+	}
101
+	utils.PrintErrorAndExit("Unknown help topic", ErrorTemplate)
102
+}

apiapp.go → cmd/commands/api/apiapp.go View File

@@ -12,16 +12,22 @@
12 12
 // License for the specific language governing permissions and limitations
13 13
 // under the License.
14 14
 
15
-package main
15
+package apiapp
16 16
 
17 17
 import (
18 18
 	"fmt"
19 19
 	"os"
20 20
 	path "path/filepath"
21 21
 	"strings"
22
+
23
+	"github.com/beego/bee/cmd/commands"
24
+	"github.com/beego/bee/cmd/commands/version"
25
+	"github.com/beego/bee/generate"
26
+	beeLogger "github.com/beego/bee/logger"
27
+	"github.com/beego/bee/utils"
22 28
 )
23 29
 
24
-var cmdApiapp = &Command{
30
+var CmdApiapp = &commands.Command{
25 31
 	// CustomFlags: true,
26 32
 	UsageLine: "api [appname]",
27 33
 	Short:     "Creates a Beego API application",
@@ -50,10 +56,9 @@ var cmdApiapp = &Command{
50 56
 	          └── object.go
51 57
 	          └── user.go
52 58
 `,
53
-	PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
59
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
54 60
 	Run:    createapi,
55 61
 }
56
-
57 62
 var apiconf = `appname = {{.Appname}}
58 63
 httpport = 8080
59 64
 runmode = dev
@@ -134,7 +139,7 @@ func init() {
134 139
 }
135 140
 `
136 141
 
137
-var apiModels = `package models
142
+var ApiModels = `package models
138 143
 
139 144
 import (
140 145
 	"errors"
@@ -189,7 +194,7 @@ func Delete(ObjectId string) {
189 194
 
190 195
 `
191 196
 
192
-var apiModels2 = `package models
197
+var ApiModels2 = `package models
193 198
 
194 199
 import (
195 200
 	"errors"
@@ -532,33 +537,32 @@ func TestGet(t *testing.T) {
532 537
 `
533 538
 
534 539
 func init() {
535
-	cmdApiapp.Flag.Var(&tables, "tables", "List of table names separated by a comma.")
536
-	cmdApiapp.Flag.Var(&driver, "driver", "Database driver. Either mysql, postgres or sqlite.")
537
-	cmdApiapp.Flag.Var(&conn, "conn", "Connection string used by the driver to connect to a database instance.")
540
+	CmdApiapp.Flag.Var(&generate.Tables, "tables", "List of table names separated by a comma.")
541
+	CmdApiapp.Flag.Var(&generate.SQLDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
542
+	CmdApiapp.Flag.Var(&generate.SQLConn, "conn", "Connection string used by the driver to connect to a database instance.")
543
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdApiapp)
538 544
 }
539 545
 
540
-func createapi(cmd *Command, args []string) int {
546
+func createapi(cmd *commands.Command, args []string) int {
541 547
 	output := cmd.Out()
542 548
 
543 549
 	if len(args) < 1 {
544
-		logger.Fatal("Argument [appname] is missing")
550
+		beeLogger.Log.Fatal("Argument [appname] is missing")
545 551
 	}
546 552
 
547 553
 	if len(args) > 1 {
548 554
 		cmd.Flag.Parse(args[1:])
549 555
 	}
550 556
 
551
-	apppath, packpath, err := checkEnv(args[0])
557
+	apppath, packpath, err := utils.CheckEnv(args[0])
552 558
 	if err != nil {
553
-		logger.Fatalf("%s", err)
559
+		beeLogger.Log.Fatalf("%s", err)
554 560
 	}
555
-	if driver == "" {
556
-		driver = "mysql"
557
-	}
558
-	if conn == "" {
561
+	if generate.SQLDriver == "" {
562
+		generate.SQLDriver = "mysql"
559 563
 	}
560 564
 
561
-	logger.Info("Creating API...")
565
+	beeLogger.Log.Info("Creating API...")
562 566
 
563 567
 	os.MkdirAll(apppath, 0755)
564 568
 	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
@@ -569,30 +573,30 @@ func createapi(cmd *Command, args []string) int {
569 573
 	os.Mkdir(path.Join(apppath, "tests"), 0755)
570 574
 	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests"), "\x1b[0m")
571 575
 	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
572
-	WriteToFile(path.Join(apppath, "conf", "app.conf"),
576
+	utils.WriteToFile(path.Join(apppath, "conf", "app.conf"),
573 577
 		strings.Replace(apiconf, "{{.Appname}}", path.Base(args[0]), -1))
574 578
 
575
-	if conn != "" {
579
+	if generate.SQLConn != "" {
576 580
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
577 581
 		maingoContent := strings.Replace(apiMainconngo, "{{.Appname}}", packpath, -1)
578
-		maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(driver), -1)
579
-		if driver == "mysql" {
582
+		maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(generate.SQLDriver), -1)
583
+		if generate.SQLDriver == "mysql" {
580 584
 			maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/go-sql-driver/mysql"`, -1)
581
-		} else if driver == "postgres" {
585
+		} else if generate.SQLDriver == "postgres" {
582 586
 			maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/lib/pq"`, -1)
583 587
 		}
584
-		WriteToFile(path.Join(apppath, "main.go"),
588
+		utils.WriteToFile(path.Join(apppath, "main.go"),
585 589
 			strings.Replace(
586 590
 				maingoContent,
587 591
 				"{{.conn}}",
588
-				conn.String(),
592
+				generate.SQLConn.String(),
589 593
 				-1,
590 594
 			),
591 595
 		)
592
-		logger.Infof("Using '%s' as 'driver'", driver)
593
-		logger.Infof("Using '%s' as 'conn'", conn)
594
-		logger.Infof("Using '%s' as 'tables'", tables)
595
-		generateAppcode(string(driver), string(conn), "3", string(tables), apppath)
596
+		beeLogger.Log.Infof("Using '%s' as 'driver'", generate.SQLDriver)
597
+		beeLogger.Log.Infof("Using '%s' as 'conn'", generate.SQLConn)
598
+		beeLogger.Log.Infof("Using '%s' as 'tables'", generate.Tables)
599
+		generate.GenerateAppcode(string(generate.SQLDriver), string(generate.SQLConn), "3", string(generate.Tables), apppath)
596 600
 	} else {
597 601
 		os.Mkdir(path.Join(apppath, "models"), 0755)
598 602
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m")
@@ -600,65 +604,31 @@ func createapi(cmd *Command, args []string) int {
600 604
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
601 605
 
602 606
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "object.go"), "\x1b[0m")
603
-		WriteToFile(path.Join(apppath, "controllers", "object.go"),
607
+		utils.WriteToFile(path.Join(apppath, "controllers", "object.go"),
604 608
 			strings.Replace(apiControllers, "{{.Appname}}", packpath, -1))
605 609
 
606 610
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "user.go"), "\x1b[0m")
607
-		WriteToFile(path.Join(apppath, "controllers", "user.go"),
611
+		utils.WriteToFile(path.Join(apppath, "controllers", "user.go"),
608 612
 			strings.Replace(apiControllers2, "{{.Appname}}", packpath, -1))
609 613
 
610 614
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
611
-		WriteToFile(path.Join(apppath, "tests", "default_test.go"),
615
+		utils.WriteToFile(path.Join(apppath, "tests", "default_test.go"),
612 616
 			strings.Replace(apiTests, "{{.Appname}}", packpath, -1))
613 617
 
614 618
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
615
-		WriteToFile(path.Join(apppath, "routers", "router.go"),
619
+		utils.WriteToFile(path.Join(apppath, "routers", "router.go"),
616 620
 			strings.Replace(apirouter, "{{.Appname}}", packpath, -1))
617 621
 
618 622
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m")
619
-		WriteToFile(path.Join(apppath, "models", "object.go"), apiModels)
623
+		utils.WriteToFile(path.Join(apppath, "models", "object.go"), ApiModels)
620 624
 
621 625
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m")
622
-		WriteToFile(path.Join(apppath, "models", "user.go"), apiModels2)
626
+		utils.WriteToFile(path.Join(apppath, "models", "user.go"), ApiModels2)
623 627
 
624 628
 		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
625
-		WriteToFile(path.Join(apppath, "main.go"),
629
+		utils.WriteToFile(path.Join(apppath, "main.go"),
626 630
 			strings.Replace(apiMaingo, "{{.Appname}}", packpath, -1))
627 631
 	}
628
-	logger.Success("New API successfully created!")
632
+	beeLogger.Log.Success("New API successfully created!")
629 633
 	return 0
630 634
 }
631
-
632
-func checkEnv(appname string) (apppath, packpath string, err error) {
633
-	gps := GetGOPATHs()
634
-	if len(gps) == 0 {
635
-		logger.Fatal("GOPATH environment variable is not set or empty")
636
-	}
637
-	currpath, _ := os.Getwd()
638
-	currpath = path.Join(currpath, appname)
639
-	for _, gpath := range gps {
640
-		gsrcpath := path.Join(gpath, "src")
641
-		if strings.HasPrefix(currpath, gsrcpath) {
642
-			packpath = strings.Replace(currpath[len(gsrcpath)+1:], string(path.Separator), "/", -1)
643
-			return currpath, packpath, nil
644
-		}
645
-	}
646
-
647
-	// In case of multiple paths in the GOPATH, by default
648
-	// we use the first path
649
-	gopath := gps[0]
650
-
651
-	logger.Warn("You current workdir is not inside $GOPATH/src.")
652
-	logger.Debugf("GOPATH: %s", __FILE__(), __LINE__(), gopath)
653
-
654
-	gosrcpath := path.Join(gopath, "src")
655
-	apppath = path.Join(gosrcpath, appname)
656
-
657
-	if _, e := os.Stat(apppath); os.IsNotExist(e) == false {
658
-		err = fmt.Errorf("Cannot create application without removing '%s' first.", apppath)
659
-		logger.Errorf("Path '%s' already exists", apppath)
660
-		return
661
-	}
662
-	packpath = strings.Join(strings.Split(apppath[len(gosrcpath)+1:], string(path.Separator)), "/")
663
-	return
664
-}

bale.go → cmd/commands/bale/bale.go View File

@@ -12,7 +12,7 @@
12 12
 // License for the specific language governing permissions and limitations
13 13
 // under the License.
14 14
 
15
-package main
15
+package bale
16 16
 
17 17
 import (
18 18
 	"bytes"
@@ -24,9 +24,15 @@ import (
24 24
 	"path/filepath"
25 25
 	"runtime"
26 26
 	"strings"
27
+
28
+	"github.com/beego/bee/cmd/commands"
29
+	"github.com/beego/bee/cmd/commands/version"
30
+	"github.com/beego/bee/config"
31
+	beeLogger "github.com/beego/bee/logger"
32
+	"github.com/beego/bee/utils"
27 33
 )
28 34
 
29
-var cmdBale = &Command{
35
+var CmdBale = &commands.Command{
30 36
 	UsageLine: "bale",
31 37
 	Short:     "Transforms non-Go files to Go source files",
32 38
 	Long: `Bale command compress all the static files in to a single binary file.
@@ -37,47 +43,46 @@ var cmdBale = &Command{
37 43
   It will auto-generate an unpack function to the main package then run it during the runtime.
38 44
   This is mainly used for zealots who are requiring 100% Go code.
39 45
 `,
40
-	PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
46
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
41 47
 	Run:    runBale,
42 48
 }
43 49
 
44
-func runBale(cmd *Command, args []string) int {
45
-	err := loadConfig()
46
-	if err != nil {
47
-		logger.Fatalf("Failed to load configuration: %s", err)
48
-	}
50
+func init() {
51
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdBale)
52
+}
49 53
 
54
+func runBale(cmd *commands.Command, args []string) int {
50 55
 	os.RemoveAll("bale")
51 56
 	os.Mkdir("bale", os.ModePerm)
52 57
 
53 58
 	// Pack and compress data
54
-	for _, p := range conf.Bale.Dirs {
55
-		if !isExist(p) {
56
-			logger.Warnf("Skipped directory: %s", p)
59
+	for _, p := range config.Conf.Bale.Dirs {
60
+		if !utils.IsExist(p) {
61
+			beeLogger.Log.Warnf("Skipped directory: %s", p)
57 62
 			continue
58 63
 		}
59
-		logger.Infof("Packaging directory: %s", p)
64
+		beeLogger.Log.Infof("Packaging directory: %s", p)
60 65
 		filepath.Walk(p, walkFn)
61 66
 	}
62 67
 
63 68
 	// Generate auto-uncompress function.
64 69
 	buf := new(bytes.Buffer)
65
-	buf.WriteString(fmt.Sprintf(BaleHeader, conf.Bale.Import,
70
+	buf.WriteString(fmt.Sprintf(BaleHeader, config.Conf.Bale.Import,
66 71
 		strings.Join(resFiles, "\",\n\t\t\""),
67 72
 		strings.Join(resFiles, ",\n\t\tbale.R")))
68 73
 
69 74
 	fw, err := os.Create("bale.go")
70 75
 	if err != nil {
71
-		logger.Fatalf("Failed to create file: %s", err)
76
+		beeLogger.Log.Fatalf("Failed to create file: %s", err)
72 77
 	}
73 78
 	defer fw.Close()
74 79
 
75 80
 	_, err = fw.Write(buf.Bytes())
76 81
 	if err != nil {
77
-		logger.Fatalf("Failed to write data: %s", err)
82
+		beeLogger.Log.Fatalf("Failed to write data: %s", err)
78 83
 	}
79 84
 
80
-	logger.Success("Baled resources successfully!")
85
+	beeLogger.Log.Success("Baled resources successfully!")
81 86
 	return 0
82 87
 }
83 88
 
@@ -146,7 +151,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
146 151
 	// Open resource files
147 152
 	fr, err := os.Open(resPath)
148 153
 	if err != nil {
149
-		logger.Fatalf("Failed to read file: %s", err)
154
+		beeLogger.Log.Fatalf("Failed to read file: %s", err)
150 155
 	}
151 156
 
152 157
 	// Convert path
@@ -164,7 +169,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
164 169
 	os.MkdirAll(path.Dir(resPath), os.ModePerm)
165 170
 	fw, err := os.Create("bale/" + resPath + ".go")
166 171
 	if err != nil {
167
-		logger.Fatalf("Failed to create file: %s", err)
172
+		beeLogger.Log.Fatalf("Failed to create file: %s", err)
168 173
 	}
169 174
 	defer fw.Close()
170 175
 
@@ -184,7 +189,7 @@ func walkFn(resPath string, info os.FileInfo, err error) error {
184 189
 }
185 190
 
186 191
 func filterSuffix(name string) bool {
187
-	for _, s := range conf.Bale.IngExt {
192
+	for _, s := range config.Conf.Bale.IngExt {
188 193
 		if strings.HasSuffix(name, s) {
189 194
 			return true
190 195
 		}

fix.go → cmd/commands/beefix/fix.go View File

@@ -1,4 +1,4 @@
1
-package main
1
+package beefix
2 2
 
3 3
 import (
4 4
 	"fmt"
@@ -9,9 +9,14 @@ import (
9 9
 	"path/filepath"
10 10
 	"regexp"
11 11
 	"strings"
12
+
13
+	"github.com/beego/bee/cmd/commands"
14
+	"github.com/beego/bee/cmd/commands/version"
15
+	beeLogger "github.com/beego/bee/logger"
16
+	"github.com/beego/bee/logger/colors"
12 17
 )
13 18
 
14
-var cmdFix = &Command{
19
+var CmdFix = &commands.Command{
15 20
 	UsageLine: "fix",
16 21
 	Short:     "Fixes your application by making it compatible with newer versions of Beego",
17 22
 	Long: `As of {{"Beego 1.6"|bold}}, there are some backward compatibility issues.
@@ -22,18 +27,19 @@ var cmdFix = &Command{
22 27
 }
23 28
 
24 29
 func init() {
25
-	cmdFix.Run = runFix
26
-	cmdFix.PreRun = func(cmd *Command, args []string) { ShowShortVersionBanner() }
30
+	CmdFix.Run = runFix
31
+	CmdFix.PreRun = func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() }
32
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdFix)
27 33
 }
28 34
 
29
-func runFix(cmd *Command, args []string) int {
35
+func runFix(cmd *commands.Command, args []string) int {
30 36
 	output := cmd.Out()
31 37
 
32
-	logger.Info("Upgrading the application...")
38
+	beeLogger.Log.Info("Upgrading the application...")
33 39
 
34 40
 	dir, err := os.Getwd()
35 41
 	if err != nil {
36
-		logger.Fatalf("Error while getting the current working directory: %s", err)
42
+		beeLogger.Log.Fatalf("Error while getting the current working directory: %s", err)
37 43
 	}
38 44
 
39 45
 	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
@@ -50,13 +56,13 @@ func runFix(cmd *Command, args []string) int {
50 56
 			return nil
51 57
 		}
52 58
 		err = fixFile(path)
53
-		fmt.Fprintf(output, GreenBold("\tfix\t")+"%s\n", path)
59
+		fmt.Fprintf(output, colors.GreenBold("\tfix\t")+"%s\n", path)
54 60
 		if err != nil {
55
-			logger.Errorf("Could not fix file: %s", err)
61
+			beeLogger.Log.Errorf("Could not fix file: %s", err)
56 62
 		}
57 63
 		return err
58 64
 	})
59
-	logger.Success("Upgrade Done!")
65
+	beeLogger.Log.Success("Upgrade Done!")
60 66
 	return 0
61 67
 }
62 68
 

+ 94
- 0
cmd/commands/command.go View File

@@ -0,0 +1,94 @@
1
+package commands
2
+
3
+import (
4
+	"flag"
5
+	"io"
6
+	"os"
7
+	"strings"
8
+
9
+	"github.com/beego/bee/logger/colors"
10
+	"github.com/beego/bee/utils"
11
+)
12
+
13
+// Command is the unit of execution
14
+type Command struct {
15
+	// Run runs the command.
16
+	// The args are the arguments after the command name.
17
+	Run func(cmd *Command, args []string) int
18
+
19
+	// PreRun performs an operation before running the command
20
+	PreRun func(cmd *Command, args []string)
21
+
22
+	// UsageLine is the one-line Usage message.
23
+	// The first word in the line is taken to be the command name.
24
+	UsageLine string
25
+
26
+	// Short is the short description shown in the 'go help' output.
27
+	Short string
28
+
29
+	// Long is the long message shown in the 'go help <this-command>' output.
30
+	Long string
31
+
32
+	// Flag is a set of flags specific to this command.
33
+	Flag flag.FlagSet
34
+
35
+	// CustomFlags indicates that the command will do its own
36
+	// flag parsing.
37
+	CustomFlags bool
38
+
39
+	// output out writer if set in SetOutput(w)
40
+	output *io.Writer
41
+}
42
+
43
+var AvailableCommands = []*Command{}
44
+var cmdUsage = `Use {{printf "bee help %s" .Name | bold}} for more information.{{endline}}`
45
+
46
+// Name returns the command's name: the first word in the Usage line.
47
+func (c *Command) Name() string {
48
+	name := c.UsageLine
49
+	i := strings.Index(name, " ")
50
+	if i >= 0 {
51
+		name = name[:i]
52
+	}
53
+	return name
54
+}
55
+
56
+// SetOutput sets the destination for Usage and error messages.
57
+// If output is nil, os.Stderr is used.
58
+func (c *Command) SetOutput(output io.Writer) {
59
+	c.output = &output
60
+}
61
+
62
+// Out returns the out writer of the current command.
63
+// If cmd.output is nil, os.Stderr is used.
64
+func (c *Command) Out() io.Writer {
65
+	if c.output != nil {
66
+		return *c.output
67
+	}
68
+	return colors.NewColorWriter(os.Stderr)
69
+}
70
+
71
+// Usage puts out the Usage for the command.
72
+func (c *Command) Usage() {
73
+	utils.Tmpl(cmdUsage, c)
74
+	os.Exit(2)
75
+}
76
+
77
+// Runnable reports whether the command can be run; otherwise
78
+// it is a documentation pseudo-command such as import path.
79
+func (c *Command) Runnable() bool {
80
+	return c.Run != nil
81
+}
82
+
83
+func (c *Command) Options() map[string]string {
84
+	options := make(map[string]string)
85
+	c.Flag.VisitAll(func(f *flag.Flag) {
86
+		defaultVal := f.DefValue
87
+		if len(defaultVal) > 0 {
88
+			options[f.Name+"="+defaultVal] = f.Usage
89
+		} else {
90
+			options[f.Name] = f.Usage
91
+		}
92
+	})
93
+	return options
94
+}

dockerize.go → cmd/commands/dockerize/dockerize.go View File

@@ -12,7 +12,7 @@
12 12
 // License for the specific language governing permissions and limitations
13 13
 // under the License.
14 14
 
15
-package main
15
+package dockerize
16 16
 
17 17
 import (
18 18
 	"flag"
@@ -21,21 +21,12 @@ import (
21 21
 	"path/filepath"
22 22
 	"strings"
23 23
 	"text/template"
24
-)
25
-
26
-var cmdDockerize = &Command{
27
-	CustomFlags: true,
28
-	UsageLine:   "dockerize",
29
-	Short:       "Generates a Dockerfile for your Beego application",
30
-	Long: `Dockerize generates a Dockerfile for your Beego Web Application.
31
-  The Dockerfile will compile, get the dependencies with {{"godep"|bold}}, and set the entrypoint.
32 24
 
33
-  {{"Example:"|bold}}
34
-    $ bee dockerize -expose="3000,80,25"
35
-  `,
36
-	PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
37
-	Run:    dockerizeApp,
38
-}
25
+	"github.com/beego/bee/cmd/commands"
26
+	"github.com/beego/bee/cmd/commands/version"
27
+	beeLogger "github.com/beego/bee/logger"
28
+	"github.com/beego/bee/utils"
29
+)
39 30
 
40 31
 const dockerBuildTemplate = `FROM {{.BaseImage}}
41 32
 
@@ -67,6 +58,20 @@ type Dockerfile struct {
67 58
 	Expose     string
68 59
 }
69 60
 
61
+var CmdDockerize = &commands.Command{
62
+	CustomFlags: true,
63
+	UsageLine:   "dockerize",
64
+	Short:       "Generates a Dockerfile for your Beego application",
65
+	Long: `Dockerize generates a Dockerfile for your Beego Web Application.
66
+  The Dockerfile will compile, get the dependencies with {{"godep"|bold}}, and set the entrypoint.
67
+
68
+  {{"Example:"|bold}}
69
+    $ bee dockerize -expose="3000,80,25"
70
+  `,
71
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
72
+	Run:    dockerizeApp,
73
+}
74
+
70 75
 var (
71 76
 	expose    string
72 77
 	baseImage string
@@ -76,19 +81,22 @@ func init() {
76 81
 	fs := flag.NewFlagSet("dockerize", flag.ContinueOnError)
77 82
 	fs.StringVar(&baseImage, "image", "library/golang", "Set the base image of the Docker container.")
78 83
 	fs.StringVar(&expose, "expose", "8080", "Port(s) to expose in the Docker container.")
79
-	cmdDockerize.Flag = *fs
84
+	CmdDockerize.Flag = *fs
85
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdDockerize)
80 86
 }
81 87
 
82
-func dockerizeApp(cmd *Command, args []string) int {
88
+func dockerizeApp(cmd *commands.Command, args []string) int {
83 89
 	if err := cmd.Flag.Parse(args); err != nil {
84
-		logger.Fatalf("Error parsing flags: %v", err.Error())
90
+		beeLogger.Log.Fatalf("Error parsing flags: %v", err.Error())
85 91
 	}
86 92
 
87
-	logger.Info("Generating Dockerfile...")
93
+	beeLogger.Log.Info("Generating Dockerfile...")
88 94
 
89 95
 	gopath := os.Getenv("GOPATH")
90 96
 	dir, err := filepath.Abs(".")
91
-	MustCheck(err)
97
+	if err != nil {
98
+		beeLogger.Log.Error(err.Error())
99
+	}
92 100
 
93 101
 	appdir := strings.Replace(dir, gopath, "", 1)
94 102
 
@@ -112,15 +120,15 @@ func dockerizeApp(cmd *Command, args []string) int {
112 120
 }
113 121
 
114 122
 func generateDockerfile(df Dockerfile) {
115
-	t := template.Must(template.New("dockerBuildTemplate").Parse(dockerBuildTemplate)).Funcs(BeeFuncMap())
123
+	t := template.Must(template.New("dockerBuildTemplate").Parse(dockerBuildTemplate)).Funcs(utils.BeeFuncMap())
116 124
 
117 125
 	f, err := os.Create("Dockerfile")
118 126
 	if err != nil {
119
-		logger.Fatalf("Error writing Dockerfile: %v", err.Error())
127
+		beeLogger.Log.Fatalf("Error writing Dockerfile: %v", err.Error())
120 128
 	}
121
-	defer CloseFile(f)
129
+	defer utils.CloseFile(f)
122 130
 
123 131
 	t.Execute(f, df)
124 132
 
125
-	logger.Success("Dockerfile generated.")
133
+	beeLogger.Log.Success("Dockerfile generated.")
126 134
 }

+ 203
- 0
cmd/commands/generate/generate.go View File

@@ -0,0 +1,203 @@
1
+package generate
2
+
3
+import (
4
+	"os"
5
+	"strings"
6
+
7
+	"github.com/beego/bee/cmd/commands"
8
+	"github.com/beego/bee/cmd/commands/version"
9
+	"github.com/beego/bee/config"
10
+	"github.com/beego/bee/generate"
11
+	"github.com/beego/bee/generate/swaggergen"
12
+	beeLogger "github.com/beego/bee/logger"
13
+	"github.com/beego/bee/utils"
14
+)
15
+
16
+var CmdGenerate = &commands.Command{
17
+	UsageLine: "generate [command]",
18
+	Short:     "Source code generator",
19
+	Long: `▶ {{"To scaffold out your entire application:"|bold}}
20
+
21
+     $ bee generate scaffold [scaffoldname] [-fields="title:string,body:text"] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
22
+
23
+  ▶ {{"To generate a Model based on fields:"|bold}}
24
+
25
+     $ bee generate model [modelname] [-fields="name:type"]
26
+
27
+  ▶ {{"To generate a controller:"|bold}}
28
+
29
+     $ bee generate controller [controllerfile]
30
+
31
+  ▶ {{"To generate a CRUD view:"|bold}}
32
+
33
+     $ bee generate view [viewpath]
34
+
35
+  ▶ {{"To generate a migration file for making database schema updates:"|bold}}
36
+
37
+     $ bee generate migration [migrationfile] [-fields="name:type"]
38
+
39
+  ▶ {{"To generate swagger doc file:"|bold}}
40
+
41
+     $ bee generate docs
42
+
43
+  ▶ {{"To generate a test case:"|bold}}
44
+
45
+     $ bee generate test [routerfile]
46
+
47
+  ▶ {{"To generate appcode based on an existing database:"|bold}}
48
+
49
+     $ bee generate appcode [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3]
50
+`,
51
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
52
+	Run:    GenerateCode,
53
+}
54
+
55
+func init() {
56
+	CmdGenerate.Flag.Var(&generate.Tables, "Tables", "List of table names separated by a comma.")
57
+	CmdGenerate.Flag.Var(&generate.SQLDriver, "SQLDriver", "Database SQLDriver. Either mysql, postgres or sqlite.")
58
+	CmdGenerate.Flag.Var(&generate.SQLConn, "SQLConn", "Connection string used by the SQLDriver to connect to a database instance.")
59
+	CmdGenerate.Flag.Var(&generate.Level, "Level", "Either 1, 2 or 3. i.e. 1=models; 2=models and controllers; 3=models, controllers and routers.")
60
+	CmdGenerate.Flag.Var(&generate.Fields, "Fields", "List of table Fields.")
61
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdGenerate)
62
+}
63
+
64
+func GenerateCode(cmd *commands.Command, args []string) int {
65
+	currpath, _ := os.Getwd()
66
+	if len(args) < 1 {
67
+		beeLogger.Log.Fatal("Command is missing")
68
+	}
69
+
70
+	gps := utils.GetGOPATHs()
71
+	if len(gps) == 0 {
72
+		beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
73
+	}
74
+
75
+	gopath := gps[0]
76
+
77
+	beeLogger.Log.Debugf("GOPATH: %s", utils.FILE(), utils.LINE(), gopath)
78
+
79
+	gcmd := args[0]
80
+	switch gcmd {
81
+	case "scaffold":
82
+		scaffold(cmd, args, currpath)
83
+	case "docs":
84
+		swaggergen.GenerateDocs(currpath)
85
+	case "appcode":
86
+		appCode(cmd, args, currpath)
87
+	case "migration":
88
+		migration(cmd, args, currpath)
89
+	case "controller":
90
+		controller(args, currpath)
91
+	case "model":
92
+		model(cmd, args, currpath)
93
+	case "view":
94
+		view(args, currpath)
95
+	default:
96
+		beeLogger.Log.Fatal("Command is missing")
97
+	}
98
+	beeLogger.Log.Successf("%s successfully generated!", strings.Title(gcmd))
99
+	return 0
100
+}
101
+
102
+func scaffold(cmd *commands.Command, args []string, currpath string) {
103
+	if len(args) < 2 {
104
+		beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
105
+	}
106
+
107
+	cmd.Flag.Parse(args[2:])
108
+	if generate.SQLDriver == "" {
109
+		generate.SQLDriver = utils.DocValue(config.Conf.Database.Driver)
110
+		if generate.SQLDriver == "" {
111
+			generate.SQLDriver = "mysql"
112
+		}
113
+	}
114
+	if generate.SQLConn == "" {
115
+		generate.SQLConn = utils.DocValue(config.Conf.Database.Conn)
116
+		if generate.SQLConn == "" {
117
+			generate.SQLConn = "root:@tcp(127.0.0.1:3306)/test"
118
+		}
119
+	}
120
+	if generate.Fields == "" {
121
+		beeLogger.Log.Hint("Fields option should not be empty, i.e. -Fields=\"title:string,body:text\"")
122
+		beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
123
+	}
124
+	sname := args[1]
125
+	generate.GenerateScaffold(sname, generate.Fields.String(), currpath, generate.SQLDriver.String(), generate.SQLConn.String())
126
+}
127
+
128
+func appCode(cmd *commands.Command, args []string, currpath string) {
129
+	cmd.Flag.Parse(args[1:])
130
+	if generate.SQLDriver == "" {
131
+		generate.SQLDriver = utils.DocValue(config.Conf.Database.Driver)
132
+		if generate.SQLDriver == "" {
133
+			generate.SQLDriver = "mysql"
134
+		}
135
+	}
136
+	if generate.SQLConn == "" {
137
+		generate.SQLConn = utils.DocValue(config.Conf.Database.Conn)
138
+		if generate.SQLConn == "" {
139
+			if generate.SQLDriver == "mysql" {
140
+				generate.SQLConn = "root:@tcp(127.0.0.1:3306)/test"
141
+			} else if generate.SQLDriver == "postgres" {
142
+				generate.SQLConn = "postgres://postgres:postgres@127.0.0.1:5432/postgres"
143
+			}
144
+		}
145
+	}
146
+	if generate.Level == "" {
147
+		generate.Level = "3"
148
+	}
149
+	beeLogger.Log.Infof("Using '%s' as 'SQLDriver'", generate.SQLDriver)
150
+	beeLogger.Log.Infof("Using '%s' as 'SQLConn'", generate.SQLConn)
151
+	beeLogger.Log.Infof("Using '%s' as 'Tables'", generate.Tables)
152
+	beeLogger.Log.Infof("Using '%s' as 'Level'", generate.Level)
153
+	generate.GenerateAppcode(generate.SQLDriver.String(), generate.SQLConn.String(), generate.Level.String(), generate.Tables.String(), currpath)
154
+}
155
+func migration(cmd *commands.Command, args []string, currpath string) {
156
+	if len(args) < 2 {
157
+		beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
158
+	}
159
+	cmd.Flag.Parse(args[2:])
160
+	mname := args[1]
161
+
162
+	beeLogger.Log.Infof("Using '%s' as migration name", mname)
163
+
164
+	upsql := ""
165
+	downsql := ""
166
+	if generate.Fields != "" {
167
+		dbMigrator := generate.NewDBDriver()
168
+		upsql = dbMigrator.GenerateCreateUp(mname)
169
+		downsql = dbMigrator.GenerateCreateDown(mname)
170
+	}
171
+	generate.GenerateMigration(mname, upsql, downsql, currpath)
172
+}
173
+
174
+func controller(args []string, currpath string) {
175
+	if len(args) == 2 {
176
+		cname := args[1]
177
+		generate.GenerateController(cname, currpath)
178
+	} else {
179
+		beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
180
+	}
181
+}
182
+
183
+func model(cmd *commands.Command, args []string, currpath string) {
184
+	if len(args) < 2 {
185
+		beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
186
+	}
187
+	cmd.Flag.Parse(args[2:])
188
+	if generate.Fields == "" {
189
+		beeLogger.Log.Hint("Fields option should not be empty, i.e. -Fields=\"title:string,body:text\"")
190
+		beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
191
+	}
192
+	sname := args[1]
193
+	generate.GenerateModel(sname, generate.Fields.String(), currpath)
194
+}
195
+
196
+func view(args []string, currpath string) {
197
+	if len(args) == 2 {
198
+		cname := args[1]
199
+		generate.GenerateView(cname, currpath)
200
+	} else {
201
+		beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
202
+	}
203
+}

+ 119
- 0
cmd/commands/hprose/hprose.go View File

@@ -0,0 +1,119 @@
1
+package hprose
2
+
3
+import (
4
+	"os"
5
+
6
+	"fmt"
7
+	"path"
8
+	"strings"
9
+
10
+	"github.com/beego/bee/cmd/commands"
11
+	"github.com/beego/bee/cmd/commands/api"
12
+	"github.com/beego/bee/cmd/commands/version"
13
+	"github.com/beego/bee/generate"
14
+	beeLogger "github.com/beego/bee/logger"
15
+	"github.com/beego/bee/utils"
16
+)
17
+
18
+var CmdHproseapp = &commands.Command{
19
+	// CustomFlags: true,
20
+	UsageLine: "hprose [appname]",
21
+	Short:     "Creates an RPC application based on Hprose and Beego frameworks",
22
+	Long: `
23
+  The command 'hprose' creates an RPC application based on both Beego and Hprose (http://hprose.com/).
24
+
25
+  {{"To scaffold out your application, use:"|bold}}
26
+
27
+      $ bee hprose [appname] [-tables=""] [-driver=mysql] [-conn=root:@tcp(127.0.0.1:3306)/test]
28
+
29
+  If 'conn' is empty, the command will generate a sample application. Otherwise the command
30
+  will connect to your database and generate models based on the existing tables.
31
+
32
+  The command 'hprose' creates a folder named [appname] with the following structure:
33
+
34
+	    ├── main.go
35
+	    ├── {{"conf"|foldername}}
36
+	    │     └── app.conf
37
+	    └── {{"models"|foldername}}
38
+	          └── object.go
39
+	          └── user.go
40
+`,
41
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
42
+	Run:    createhprose,
43
+}
44
+
45
+func init() {
46
+	CmdHproseapp.Flag.Var(&generate.Tables, "tables", "List of table names separated by a comma.")
47
+	CmdHproseapp.Flag.Var(&generate.SQLDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
48
+	CmdHproseapp.Flag.Var(&generate.SQLConn, "conn", "Connection string used by the driver to connect to a database instance.")
49
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdHproseapp)
50
+}
51
+
52
+func createhprose(cmd *commands.Command, args []string) int {
53
+	output := cmd.Out()
54
+
55
+	if len(args) != 1 {
56
+		beeLogger.Log.Fatal("Argument [appname] is missing")
57
+	}
58
+
59
+	curpath, _ := os.Getwd()
60
+	if len(args) > 1 {
61
+		cmd.Flag.Parse(args[1:])
62
+	}
63
+	apppath, packpath, err := utils.CheckEnv(args[0])
64
+	if err != nil {
65
+		beeLogger.Log.Fatalf("%s", err)
66
+	}
67
+	if generate.SQLDriver == "" {
68
+		generate.SQLDriver = "mysql"
69
+	}
70
+	beeLogger.Log.Info("Creating Hprose application...")
71
+
72
+	os.MkdirAll(apppath, 0755)
73
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath, "\x1b[0m")
74
+	os.Mkdir(path.Join(apppath, "conf"), 0755)
75
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf"), "\x1b[0m")
76
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
77
+	utils.WriteToFile(path.Join(apppath, "conf", "app.conf"),
78
+		strings.Replace(generate.Hproseconf, "{{.Appname}}", args[0], -1))
79
+
80
+	if generate.SQLConn != "" {
81
+		beeLogger.Log.Infof("Using '%s' as 'driver'", generate.SQLDriver)
82
+		beeLogger.Log.Infof("Using '%s' as 'conn'", generate.SQLConn)
83
+		beeLogger.Log.Infof("Using '%s' as 'tables'", generate.Tables)
84
+		generate.GenerateHproseAppcode(string(generate.SQLDriver), string(generate.SQLConn), "1", string(generate.Tables), path.Join(curpath, args[0]))
85
+
86
+		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
87
+		maingoContent := strings.Replace(generate.HproseMainconngo, "{{.Appname}}", packpath, -1)
88
+		maingoContent = strings.Replace(maingoContent, "{{.DriverName}}", string(generate.SQLDriver), -1)
89
+		maingoContent = strings.Replace(maingoContent, "{{HproseFunctionList}}", strings.Join(generate.HproseAddFunctions, ""), -1)
90
+		if generate.SQLDriver == "mysql" {
91
+			maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/go-sql-driver/mysql"`, -1)
92
+		} else if generate.SQLDriver == "postgres" {
93
+			maingoContent = strings.Replace(maingoContent, "{{.DriverPkg}}", `_ "github.com/lib/pq"`, -1)
94
+		}
95
+		utils.WriteToFile(path.Join(apppath, "main.go"),
96
+			strings.Replace(
97
+				maingoContent,
98
+				"{{.conn}}",
99
+				generate.SQLConn.String(),
100
+				-1,
101
+			),
102
+		)
103
+	} else {
104
+		os.Mkdir(path.Join(apppath, "models"), 0755)
105
+		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models"), "\x1b[0m")
106
+
107
+		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "object.go"), "\x1b[0m")
108
+		utils.WriteToFile(path.Join(apppath, "models", "object.go"), apiapp.ApiModels)
109
+
110
+		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models", "user.go"), "\x1b[0m")
111
+		utils.WriteToFile(path.Join(apppath, "models", "user.go"), apiapp.ApiModels2)
112
+
113
+		fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
114
+		utils.WriteToFile(path.Join(apppath, "main.go"),
115
+			strings.Replace(generate.HproseMaingo, "{{.Appname}}", packpath, -1))
116
+	}
117
+	beeLogger.Log.Success("New Hprose application successfully created!")
118
+	return 0
119
+}

migrate.go → cmd/commands/migrate/migrate.go View File

@@ -1,18 +1,4 @@
1
-// Copyright 2013 bee authors
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
-// not use this file except in compliance with the License. You may obtain
5
-// a copy of the License at
6
-//
7
-//     http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
-// License for the specific language governing permissions and limitations
13
-// under the License.
14
-
15
-package main
1
+package migrate
16 2
 
17 3
 import (
18 4
 	"database/sql"
@@ -23,9 +9,16 @@ import (
23 9
 	"strconv"
24 10
 	"strings"
25 11
 	"time"
12
+
13
+	"github.com/beego/bee/cmd/commands"
14
+	"github.com/beego/bee/cmd/commands/version"
15
+	"github.com/beego/bee/config"
16
+	"github.com/beego/bee/utils"
17
+
18
+	beeLogger "github.com/beego/bee/logger"
26 19
 )
27 20
 
28
-var cmdMigrate = &Command{
21
+var CmdMigrate = &commands.Command{
29 22
 	UsageLine: "migrate [Command]",
30 23
 	Short:     "Runs database migrations",
31 24
 	Long: `The command 'migrate' allows you to run database migrations to keep it up-to-date.
@@ -46,100 +39,75 @@ var cmdMigrate = &Command{
46 39
 
47 40
     $ bee migrate refresh [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
48 41
 `,
49
-	PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
50
-	Run:    runMigration,
42
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
43
+	Run:    RunMigration,
51 44
 }
52 45
 
53
-var mDriver docValue
54
-var mConn docValue
46
+var mDriver utils.DocValue
47
+var mConn utils.DocValue
55 48
 
56 49
 func init() {
57
-	cmdMigrate.Flag.Var(&mDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
58
-	cmdMigrate.Flag.Var(&mConn, "conn", "Connection string used by the driver to connect to a database instance.")
50
+	CmdMigrate.Flag.Var(&mDriver, "driver", "Database driver. Either mysql, postgres or sqlite.")
51
+	CmdMigrate.Flag.Var(&mConn, "conn", "Connection string used by the driver to connect to a database instance.")
52
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdMigrate)
59 53
 }
60 54
 
61 55
 // runMigration is the entry point for starting a migration
62
-func runMigration(cmd *Command, args []string) int {
56
+func RunMigration(cmd *commands.Command, args []string) int {
63 57
 	currpath, _ := os.Getwd()
64 58
 
65
-	gps := GetGOPATHs()
59
+	gps := utils.GetGOPATHs()
66 60
 	if len(gps) == 0 {
67
-		logger.Fatal("GOPATH environment variable is not set or empty")
61
+		beeLogger.Log.Fatal("GOPATH environment variable is not set or empty")
68 62
 	}
69 63
 
70 64
 	gopath := gps[0]
71 65
 
72
-	logger.Debugf("GOPATH: %s", __FILE__(), __LINE__(), gopath)
73
-
74
-	// Load the configuration
75
-	err := loadConfig()
76
-	if err != nil {
77
-		logger.Errorf("Failed to load configuration: %s", err)
78
-	}
66
+	beeLogger.Log.Debugf("GOPATH: %s", utils.FILE(), utils.LINE(), gopath)
79 67
 
80 68
 	// Getting command line arguments
81 69
 	if len(args) != 0 {
82 70
 		cmd.Flag.Parse(args[1:])
83 71
 	}
84 72
 	if mDriver == "" {
85
-		mDriver = docValue(conf.Database.Driver)
73
+		mDriver = utils.DocValue(config.Conf.Database.Driver)
86 74
 		if mDriver == "" {
87 75
 			mDriver = "mysql"
88 76
 		}
89 77
 	}
90 78
 	if mConn == "" {
91
-		mConn = docValue(conf.Database.Conn)
79
+		mConn = utils.DocValue(config.Conf.Database.Conn)
92 80
 		if mConn == "" {
93 81
 			mConn = "root:@tcp(127.0.0.1:3306)/test"
94 82
 		}
95 83
 	}
96
-	logger.Infof("Using '%s' as 'driver'", mDriver)
97
-	logger.Infof("Using '%s' as 'conn'", mConn)
84
+	beeLogger.Log.Infof("Using '%s' as 'driver'", mDriver)
85
+	beeLogger.Log.Infof("Using '%s' as 'conn'", mConn)
98 86
 	driverStr, connStr := string(mDriver), string(mConn)
99 87
 	if len(args) == 0 {
100 88
 		// run all outstanding migrations
101
-		logger.Info("Running all outstanding migrations")
102
-		migrateUpdate(currpath, driverStr, connStr)
89
+		beeLogger.Log.Info("Running all outstanding migrations")
90
+		MigrateUpdate(currpath, driverStr, connStr)
103 91
 	} else {
104 92
 		mcmd := args[0]
105 93
 		switch mcmd {
106 94
 		case "rollback":
107
-			logger.Info("Rolling back the last migration operation")
108
-			migrateRollback(currpath, driverStr, connStr)
95
+			beeLogger.Log.Info("Rolling back the last migration operation")
96
+			MigrateRollback(currpath, driverStr, connStr)
109 97
 		case "reset":
110
-			logger.Info("Reseting all migrations")
111
-			migrateReset(currpath, driverStr, connStr)
98
+			beeLogger.Log.Info("Reseting all migrations")
99
+			MigrateReset(currpath, driverStr, connStr)
112 100
 		case "refresh":
113
-			logger.Info("Refreshing all migrations")
114
-			migrateRefresh(currpath, driverStr, connStr)
101
+			beeLogger.Log.Info("Refreshing all migrations")
102
+			MigrateRefresh(currpath, driverStr, connStr)
115 103
 		default:
116
-			logger.Fatal("Command is missing")
104
+			beeLogger.Log.Fatal("Command is missing")
117 105
 		}
118 106
 	}
119
-	logger.Success("Migration successful!")
107
+	beeLogger.Log.Success("Migration successful!")
120 108
 	return 0
121 109
 }
122 110
 
123
-// migrateUpdate does the schema update
124
-func migrateUpdate(currpath, driver, connStr string) {
125
-	migrate("upgrade", currpath, driver, connStr)
126
-}
127
-
128
-// migrateRollback rolls back the latest migration
129
-func migrateRollback(currpath, driver, connStr string) {
130
-	migrate("rollback", currpath, driver, connStr)
131
-}
132
-
133
-// migrateReset rolls back all migrations
134
-func migrateReset(currpath, driver, connStr string) {
135
-	migrate("reset", currpath, driver, connStr)
136
-}
137
-
138
-// migrationRefresh rolls back all migrations and start over again
139
-func migrateRefresh(currpath, driver, connStr string) {
140
-	migrate("refresh", currpath, driver, connStr)
141
-}
142
-
143 111
 // migrate generates source code, build it, and invoke the binary who does the actual migration
144 112
 func migrate(goal, currpath, driver, connStr string) {
145 113
 	dir := path.Join(currpath, "database", "migrations")
@@ -153,7 +121,7 @@ func migrate(goal, currpath, driver, connStr string) {
153 121
 	// Connect to database
154 122
 	db, err := sql.Open(driver, connStr)
155 123
 	if err != nil {
156
-		logger.Fatalf("Could not connect to database using '%s': %s", connStr, err)
124
+		beeLogger.Log.Fatalf("Could not connect to database using '%s': %s", connStr, err)
157 125
 	}
158 126
 	defer db.Close()
159 127
 
@@ -171,44 +139,44 @@ func migrate(goal, currpath, driver, connStr string) {
171 139
 func checkForSchemaUpdateTable(db *sql.DB, driver string) {
172 140
 	showTableSQL := showMigrationsTableSQL(driver)
173 141
 	if rows, err := db.Query(showTableSQL); err != nil {
174
-		logger.Fatalf("Could not show migrations table: %s", err)
142
+		beeLogger.Log.Fatalf("Could not show migrations table: %s", err)
175 143
 	} else if !rows.Next() {
176 144
 		// No migrations table, create new ones
177 145
 		createTableSQL := createMigrationsTableSQL(driver)
178 146
 
179
-		logger.Infof("Creating 'migrations' table...")
147
+		beeLogger.Log.Infof("Creating 'migrations' table...")
180 148
 
181 149
 		if _, err := db.Query(createTableSQL); err != nil {
182
-			logger.Fatalf("Could not create migrations table: %s", err)
150
+			beeLogger.Log.Fatalf("Could not create migrations table: %s", err)
183 151
 		}
184 152
 	}
185 153
 
186 154
 	// Checking that migrations table schema are expected
187 155
 	selectTableSQL := selectMigrationsTableSQL(driver)
188 156
 	if rows, err := db.Query(selectTableSQL); err != nil {
189
-		logger.Fatalf("Could not show columns of migrations table: %s", err)
157
+		beeLogger.Log.Fatalf("Could not show columns of migrations table: %s", err)
190 158
 	} else {
191 159
 		for rows.Next() {
192 160
 			var fieldBytes, typeBytes, nullBytes, keyBytes, defaultBytes, extraBytes []byte
193 161
 			if err := rows.Scan(&fieldBytes, &typeBytes, &nullBytes, &keyBytes, &defaultBytes, &extraBytes); err != nil {
194
-				logger.Fatalf("Could not read column information: %s", err)
162
+				beeLogger.Log.Fatalf("Could not read column information: %s", err)
195 163
 			}
196 164
 			fieldStr, typeStr, nullStr, keyStr, defaultStr, extraStr :=
197 165
 				string(fieldBytes), string(typeBytes), string(nullBytes), string(keyBytes), string(defaultBytes), string(extraBytes)
198 166
 			if fieldStr == "id_migration" {
199 167
 				if keyStr != "PRI" || extraStr != "auto_increment" {
200
-					logger.Hint("Expecting KEY: PRI, EXTRA: auto_increment")
201
-					logger.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr)
168
+					beeLogger.Log.Hint("Expecting KEY: PRI, EXTRA: auto_increment")
169
+					beeLogger.Log.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr)
202 170
 				}
203 171
 			} else if fieldStr == "name" {
204 172
 				if !strings.HasPrefix(typeStr, "varchar") || nullStr != "YES" {
205
-					logger.Hint("Expecting TYPE: varchar, NULL: YES")
206
-					logger.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr)
173
+					beeLogger.Log.Hint("Expecting TYPE: varchar, NULL: YES")
174
+					beeLogger.Log.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr)
207 175
 				}
208 176
 			} else if fieldStr == "created_at" {
209 177
 				if typeStr != "timestamp" || defaultStr != "CURRENT_TIMESTAMP" {
210
-					logger.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP")
211
-					logger.Fatalf("Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s", typeStr, defaultStr)
178
+					beeLogger.Log.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP")
179
+					beeLogger.Log.Fatalf("Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s", typeStr, defaultStr)
212 180
 				}
213 181
 			}
214 182
 		}
@@ -252,22 +220,22 @@ func selectMigrationsTableSQL(driver string) string {
252 220
 func getLatestMigration(db *sql.DB, goal string) (file string, createdAt int64) {
253 221
 	sql := "SELECT name FROM migrations where status = 'update' ORDER BY id_migration DESC LIMIT 1"
254 222
 	if rows, err := db.Query(sql); err != nil {
255
-		logger.Fatalf("Could not retrieve migrations: %s", err)
223
+		beeLogger.Log.Fatalf("Could not retrieve migrations: %s", err)
256 224
 	} else {
257 225
 		if rows.Next() {
258 226
 			if err := rows.Scan(&file); err != nil {
259
-				logger.Fatalf("Could not read migrations in database: %s", err)
227
+				beeLogger.Log.Fatalf("Could not read migrations in database: %s", err)
260 228
 			}
261 229
 			createdAtStr := file[len(file)-15:]
262 230
 			if t, err := time.Parse("20060102_150405", createdAtStr); err != nil {
263
-				logger.Fatalf("Could not parse time: %s", err)
231
+				beeLogger.Log.Fatalf("Could not parse time: %s", err)
264 232
 			} else {
265 233
 				createdAt = t.Unix()
266 234
 			}
267 235
 		} else {
268 236
 			// migration table has no 'update' record, no point rolling back
269 237
 			if goal == "rollback" {
270
-				logger.Fatal("There is nothing to rollback")
238
+				beeLogger.Log.Fatal("There is nothing to rollback")
271 239
 			}
272 240
 			file, createdAt = "", 0
273 241
 		}
@@ -279,7 +247,7 @@ func getLatestMigration(db *sql.DB, goal string) (file string, createdAt int64)
279 247
 func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime int64, latestName string, task string) {
280 248
 	changeDir(dir)
281 249
 	if f, err := os.OpenFile(source, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err != nil {
282
-		logger.Fatalf("Could not create file: %s", err)
250
+		beeLogger.Log.Fatalf("Could not create file: %s", err)
283 251
 	} else {
284 252
 		content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1)
285 253
 		content = strings.Replace(content, "{{ConnStr}}", connStr, -1)
@@ -287,9 +255,9 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in
287 255
 		content = strings.Replace(content, "{{LatestName}}", latestName, -1)
288 256
 		content = strings.Replace(content, "{{Task}}", task, -1)
289 257
 		if _, err := f.WriteString(content); err != nil {
290
-			logger.Fatalf("Could not write to file: %s", err)
258
+			beeLogger.Log.Fatalf("Could not write to file: %s", err)
291 259
 		}
292
-		CloseFile(f)
260
+		utils.CloseFile(f)
293 261
 	}
294 262
 }
295 263
 
@@ -298,7 +266,7 @@ func buildMigrationBinary(dir, binary string) {
298 266
 	changeDir(dir)
299 267
 	cmd := exec.Command("go", "build", "-o", binary)
300 268
 	if out, err := cmd.CombinedOutput(); err != nil {
301
-		logger.Errorf("Could not build migration binary: %s", err)
269
+		beeLogger.Log.Errorf("Could not build migration binary: %s", err)
302 270
 		formatShellErrOutput(string(out))
303 271
 		removeTempFile(dir, binary)
304 272
 		removeTempFile(dir, binary+".go")
@@ -312,7 +280,7 @@ func runMigrationBinary(dir, binary string) {
312 280
 	cmd := exec.Command("./" + binary)
313 281
 	if out, err := cmd.CombinedOutput(); err != nil {
314 282
 		formatShellOutput(string(out))
315
-		logger.Errorf("Could not run migration binary: %s", err)
283
+		beeLogger.Log.Errorf("Could not run migration binary: %s", err)
316 284
 		removeTempFile(dir, binary)
317 285
 		removeTempFile(dir, binary+".go")
318 286
 		os.Exit(2)
@@ -325,7 +293,7 @@ func runMigrationBinary(dir, binary string) {
325 293
 // It exits the system when encouter an error
326 294
 func changeDir(dir string) {
327 295
 	if err := os.Chdir(dir); err != nil {
328
-		logger.Fatalf("Could not find migration directory: %s", err)
296
+		beeLogger.Log.Fatalf("Could not find migration directory: %s", err)
329 297
 	}
330 298
 }
331 299
 
@@ -333,7 +301,7 @@ func changeDir(dir string) {
333 301
 func removeTempFile(dir, file string) {
334 302
 	changeDir(dir)
335 303
 	if err := os.Remove(file); err != nil {
336
-		logger.Warnf("Could not remove temporary file: %s", err)
304
+		beeLogger.Log.Warnf("Could not remove temporary file: %s", err)
337 305
 	}
338 306
 }
339 307
 
@@ -341,7 +309,7 @@ func removeTempFile(dir, file string) {
341 309
 func formatShellErrOutput(o string) {
342 310
 	for _, line := range strings.Split(o, "\n") {
343 311
 		if line != "" {
344
-			logger.Errorf("|> %s", line)
312
+			beeLogger.Log.Errorf("|> %s", line)
345 313
 		}
346 314
 	}
347 315
 }
@@ -350,7 +318,7 @@ func formatShellErrOutput(o string) {
350 318
 func formatShellOutput(o string) {
351 319
 	for _, line := range strings.Split(o, "\n") {
352 320
 		if line != "" {
353
-			logger.Infof("|> %s", line)
321
+			beeLogger.Log.Infof("|> %s", line)
354 322
 		}
355 323
 	}
356 324
 }
@@ -421,3 +389,23 @@ CREATE TABLE migrations (
421 389
 	status migrations_status
422 390
 )`
423 391
 )
392
+
393
+// MigrateUpdate does the schema update
394
+func MigrateUpdate(currpath, driver, connStr string) {
395
+	migrate("upgrade", currpath, driver, connStr)
396
+}
397
+
398
+// MigrateRollback rolls back the latest migration
399
+func MigrateRollback(currpath, driver, connStr string) {
400
+	migrate("rollback", currpath, driver, connStr)
401
+}
402
+
403
+// MigrateReset rolls back all migrations
404
+func MigrateReset(currpath, driver, connStr string) {
405
+	migrate("reset", currpath, driver, connStr)
406
+}
407
+
408
+// migrationRefresh rolls back all migrations and start over again
409
+func MigrateRefresh(currpath, driver, connStr string) {
410
+	migrate("refresh", currpath, driver, connStr)
411
+}

new.go → cmd/commands/new/new.go View File

@@ -12,16 +12,22 @@
12 12
 // License for the specific language governing permissions and limitations
13 13
 // under the License.
14 14
 
15
-package main
15
+package new
16 16
 
17 17
 import (
18 18
 	"fmt"
19 19
 	"os"
20 20
 	path "path/filepath"
21 21
 	"strings"
22
+
23
+	"github.com/beego/bee/cmd/commands"
24
+	"github.com/beego/bee/cmd/commands/version"
25
+	beeLogger "github.com/beego/bee/logger"
26
+	"github.com/beego/bee/logger/colors"
27
+	"github.com/beego/bee/utils"
22 28
 )
23 29
 
24
-var cmdNew = &Command{
30
+var CmdNew = &commands.Command{
25 31
 	UsageLine: "new [appname]",
26 32
 	Short:     "Creates a Beego application",
27 33
 	Long: `
@@ -47,74 +53,8 @@ Creates a Beego application for the given app name in the current directory.
47 53
                   └── index.tpl
48 54
 
49 55
 `,
50
-	PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
51
-	Run:    createApp,
52
-}
53
-
54
-func createApp(cmd *Command, args []string) int {
55
-	output := cmd.Out()
56
-	if len(args) != 1 {
57
-		logger.Fatal("Argument [appname] is missing")
58
-	}
59
-
60
-	apppath, packpath, err := checkEnv(args[0])
61
-	if err != nil {
62
-		logger.Fatalf("%s", err)
63
-	}
64
-
65
-	if isExist(apppath) {
66
-		logger.Errorf(bold("Application '%s' already exists"), apppath)
67
-		logger.Warn(bold("Do you want to overwrite it? [Yes|No] "))
68
-		if !askForConfirmation() {
69
-			os.Exit(2)
70
-		}
71
-	}
72
-
73
-	logger.Info("Creating application...")
74
-
75
-	os.MkdirAll(apppath, 0755)
76
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath+string(path.Separator), "\x1b[0m")
77
-	os.Mkdir(path.Join(apppath, "conf"), 0755)
78
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf")+string(path.Separator), "\x1b[0m")
79
-	os.Mkdir(path.Join(apppath, "controllers"), 0755)
80
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers")+string(path.Separator), "\x1b[0m")
81
-	os.Mkdir(path.Join(apppath, "models"), 0755)
82
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models")+string(path.Separator), "\x1b[0m")
83
-	os.Mkdir(path.Join(apppath, "routers"), 0755)
84
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
85
-	os.Mkdir(path.Join(apppath, "tests"), 0755)
86
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests")+string(path.Separator), "\x1b[0m")
87
-	os.Mkdir(path.Join(apppath, "static"), 0755)
88
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static")+string(path.Separator), "\x1b[0m")
89
-	os.Mkdir(path.Join(apppath, "static", "js"), 0755)
90
-	WriteToFile(path.Join(apppath, "static", "js", "reload.min.js"), reloadJsClient)
91
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "js")+string(path.Separator), "\x1b[0m")
92
-	os.Mkdir(path.Join(apppath, "static", "css"), 0755)
93
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "css")+string(path.Separator), "\x1b[0m")
94
-	os.Mkdir(path.Join(apppath, "static", "img"), 0755)
95
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "img")+string(path.Separator), "\x1b[0m")
96
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views")+string(path.Separator), "\x1b[0m")
97
-	os.Mkdir(path.Join(apppath, "views"), 0755)
98
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
99
-	WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1))
100
-
101
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "default.go"), "\x1b[0m")
102
-	WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers)
103
-
104
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views", "index.tpl"), "\x1b[0m")
105
-	WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl)
106
-
107
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
108
-	WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", packpath, -1))
109
-
110
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
111
-	WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", packpath, -1))
112
-
113
-	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
114
-	WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", packpath, -1))
115
-
116
-	logger.Success("New application successfully created!")
117
-	return 0
56
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
57
+	Run:    CreateApp,
118 58
 }
119 59
 
120 60
 var appconf = `appname = {{.Appname}}
@@ -303,3 +243,73 @@ var indextpl = `<!DOCTYPE html>
303 243
 
304 244
 var reloadJsClient = `function b(a){var c=new WebSocket(a);c.onclose=function(){setTimeout(function(){b(a)},2E3)};c.onmessage=function(){location.reload()}}try{if(window.WebSocket)try{b("ws://localhost:12450/reload")}catch(a){console.error(a)}else console.log("Your browser does not support WebSockets.")}catch(a){console.error("Exception during connecting to Reload:",a)};
305 245
 `
246
+
247
+func init() {
248
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdNew)
249
+}
250
+
251
+func CreateApp(cmd *commands.Command, args []string) int {
252
+	output := cmd.Out()
253
+	if len(args) != 1 {
254
+		beeLogger.Log.Fatal("Argument [appname] is missing")
255
+	}
256
+
257
+	apppath, packpath, err := utils.CheckEnv(args[0])
258
+	if err != nil {
259
+		beeLogger.Log.Fatalf("%s", err)
260
+	}
261
+
262
+	if utils.IsExist(apppath) {
263
+		beeLogger.Log.Errorf(colors.Bold("Application '%s' already exists"), apppath)
264
+		beeLogger.Log.Warn(colors.Bold("Do you want to overwrite it? [Yes|No] "))
265
+		if !utils.AskForConfirmation() {
266
+			os.Exit(2)
267
+		}
268
+	}
269
+
270
+	beeLogger.Log.Info("Creating application...")
271
+
272
+	os.MkdirAll(apppath, 0755)
273
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", apppath+string(path.Separator), "\x1b[0m")
274
+	os.Mkdir(path.Join(apppath, "conf"), 0755)
275
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf")+string(path.Separator), "\x1b[0m")
276
+	os.Mkdir(path.Join(apppath, "controllers"), 0755)
277
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers")+string(path.Separator), "\x1b[0m")
278
+	os.Mkdir(path.Join(apppath, "models"), 0755)
279
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "models")+string(path.Separator), "\x1b[0m")
280
+	os.Mkdir(path.Join(apppath, "routers"), 0755)
281
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers")+string(path.Separator), "\x1b[0m")
282
+	os.Mkdir(path.Join(apppath, "tests"), 0755)
283
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests")+string(path.Separator), "\x1b[0m")
284
+	os.Mkdir(path.Join(apppath, "static"), 0755)
285
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static")+string(path.Separator), "\x1b[0m")
286
+	os.Mkdir(path.Join(apppath, "static", "js"), 0755)
287
+	utils.WriteToFile(path.Join(apppath, "static", "js", "reload.min.js"), reloadJsClient)
288
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "js")+string(path.Separator), "\x1b[0m")
289
+	os.Mkdir(path.Join(apppath, "static", "css"), 0755)
290
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "css")+string(path.Separator), "\x1b[0m")
291
+	os.Mkdir(path.Join(apppath, "static", "img"), 0755)
292
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "static", "img")+string(path.Separator), "\x1b[0m")
293
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views")+string(path.Separator), "\x1b[0m")
294
+	os.Mkdir(path.Join(apppath, "views"), 0755)
295
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "conf", "app.conf"), "\x1b[0m")
296
+	utils.WriteToFile(path.Join(apppath, "conf", "app.conf"), strings.Replace(appconf, "{{.Appname}}", path.Base(args[0]), -1))
297
+
298
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "controllers", "default.go"), "\x1b[0m")
299
+	utils.WriteToFile(path.Join(apppath, "controllers", "default.go"), controllers)
300
+
301
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "views", "index.tpl"), "\x1b[0m")
302
+	utils.WriteToFile(path.Join(apppath, "views", "index.tpl"), indextpl)
303
+
304
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "routers", "router.go"), "\x1b[0m")
305
+	utils.WriteToFile(path.Join(apppath, "routers", "router.go"), strings.Replace(router, "{{.Appname}}", packpath, -1))
306
+
307
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "tests", "default_test.go"), "\x1b[0m")
308
+	utils.WriteToFile(path.Join(apppath, "tests", "default_test.go"), strings.Replace(test, "{{.Appname}}", packpath, -1))
309
+
310
+	fmt.Fprintf(output, "\t%s%screate%s\t %s%s\n", "\x1b[32m", "\x1b[1m", "\x1b[21m", path.Join(apppath, "main.go"), "\x1b[0m")
311
+	utils.WriteToFile(path.Join(apppath, "main.go"), strings.Replace(maingo, "{{.Appname}}", packpath, -1))
312
+
313
+	beeLogger.Log.Success("New application successfully created!")
314
+	return 0
315
+}

pack.go → cmd/commands/pack/pack.go View File

@@ -1,18 +1,4 @@
1
-// Copyright 2013 bee authors
2
-//
3
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
-// not use this file except in compliance with the License. You may obtain
5
-// a copy of the License at
6
-//
7
-//     http://www.apache.org/licenses/LICENSE-2.0
8
-//
9
-// Unless required by applicable law or agreed to in writing, software
10
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
-// License for the specific language governing permissions and limitations
13
-// under the License.
14
-
15
-package main
1
+package pack
16 2
 
17 3
 import (
18 4
 	"archive/tar"
@@ -31,9 +17,14 @@ import (
31 17
 	"strings"
32 18
 	"syscall"
33 19
 	"time"
20
+
21
+	"github.com/beego/bee/cmd/commands"
22
+	"github.com/beego/bee/cmd/commands/version"
23
+	beeLogger "github.com/beego/bee/logger"
24
+	"github.com/beego/bee/utils"
34 25
 )
35 26
 
36
-var cmdPack = &Command{
27
+var CmdPack = &commands.Command{
37 28
 	CustomFlags: true,
38 29
 	UsageLine:   "pack",
39 30
 	Short:       "Compresses a Beego application into a single file",
@@ -43,7 +34,7 @@ var cmdPack = &Command{
43 34
   {{"Example:"|bold}}
44 35
     $ bee pack -v -ba="-ldflags '-s -w'"
45 36
 `,
46
-	PreRun: func(cmd *Command, args []string) { ShowShortVersionBanner() },
37
+	PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
47 38
 	Run:    packApp,
48 39
 }
49 40
 
@@ -52,27 +43,16 @@ var (
52 43
 	excludeP  string
53 44
 	excludeS  string
54 45
 	outputP   string
55
-	excludeR  ListOpts
46
+	excludeR  utils.ListOpts
56 47
 	fsym      bool
57 48
 	ssym      bool
58 49
 	build     bool
59 50
 	buildArgs string
60
-	buildEnvs ListOpts
51
+	buildEnvs utils.ListOpts
61 52
 	verbose   bool
62 53
 	format    string
63 54
 )
64 55
 
65
-type ListOpts []string
66
-
67
-func (opts *ListOpts) String() string {
68
-	return fmt.Sprint(*opts)
69
-}
70
-
71
-func (opts *ListOpts) Set(value string) error {
72
-	*opts = append(*opts, value)
73
-	return nil
74
-}
75
-
76 56
 func init() {
77 57
 	fs := flag.NewFlagSet("pack", flag.ContinueOnError)
78 58
 	fs.StringVar(&appPath, "p", "", "Set the application path. Defaults to the current path.")
@@ -87,7 +67,8 @@ func init() {
87 67
 	fs.BoolVar(&fsym, "fs", false, "Tell the command to follow symlinks. Defaults to false.")
88 68
 	fs.BoolVar(&ssym, "ss", false, "Tell the command to skip symlinks. Defaults to false.")
89 69
 	fs.BoolVar(&verbose, "v", false, "Be more verbose during the operation. Defaults to false.")
90
-	cmdPack.Flag = *fs
70
+	CmdPack.Flag = *fs
71
+	commands.AvailableCommands = append(commands.AvailableCommands, CmdPack)
91 72
 }
92 73
 
93 74
 type walker interface {
@@ -115,10 +96,6 @@ type walkFileTree struct {
115 96
 	output        *io.Writer
116 97
 }
117 98
 
118
-func (wft *walkFileTree) setPrefix(prefix string) {
119
-	wft.prefix = prefix
120
-}
121
-
122 99
 func (wft *walkFileTree) isExclude(fPath string) bool {
123 100
 	if fPath == "" {
124 101
 		return true
@@ -316,12 +293,12 @@ func (wft *tarWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
316 293
 		return false, err
317 294
 	}
318 295
 
319
-	if isSym == false {
296
+	if !isSym {
320 297
 		fr, err := os.Open(fpath)
321 298
 		if err != nil {
322 299
 			return false, err
323 300
 		}
324
-		defer CloseFile(fr)
301
+		defer utils.CloseFile(fr)
325 302
 		_, err = io.Copy(tw, fr)
326 303
 		if err != nil {
327 304
 			return false, err
@@ -352,12 +329,12 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
352 329
 		return false, err
353 330
 	}
354 331
 
355
-	if isSym == false {
332
+	if !isSym {
356 333
 		fr, err := os.Open(fpath)
357 334
 		if err != nil {
358 335
 			return false, err
359 336
 		}
360
-		defer CloseFile(fr)
337
+		defer utils.CloseFile(fr)
361 338
 		_, err = io.Copy(w, fr)
362 339
 		if err != nil {
363 340
 			return false, err
@@ -379,10 +356,10 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
379 356
 func packDirectory(output io.Writer, excludePrefix []string, excludeSuffix []string,
380 357
 	excludeRegexp []*regexp.Regexp, includePath ...string) (err error) {
381 358
 
382
-	logger.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":"))
383
-	logger.Infof("Excluding relpath suffix: %s", strings.Join(excludeSuffix, ":"))
359
+	beeLogger.Log.Infof("Excluding relpath prefix: %s", strings.Join(excludePrefix, ":"))
360
+	beeLogger.Log.Infof("Excluding relpath suffix: %s", strings.Join(excludeSuffix, ":"))
384 361
 	if len(excludeRegexp) > 0 {
385
-		logger.Infof("Excluding filename regex: `%s`", strings.Join(excludeR, "`, `"))
362
+		beeLogger.Log.Infof("Excluding filename regex: `%s`", strings.Join(excludeR, "`, `"))
386 363
 	}
387 364
 
388 365
 	w, err := os.OpenFile(outputP, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
@@ -437,7 +414,7 @@ func packDirectory(output io.Writer, excludePrefix []string, excludeSuffix []str
437 414
 	return
438 415
 }
439 416
 
440
-func packApp(cmd *Command, args []string) int {
417
+func packApp(cmd *commands.Command, args []string) int {
441 418
 	output := cmd.Out()
442 419
 	curPath, _ := os.Getwd()
443 420
 	thePath := ""
@@ -454,19 +431,19 @@ func packApp(cmd *Command, args []string) int {
454 431
 	}
455 432
 	cmd.Flag.Parse(nArgs)
456 433
 
457
-	if path.IsAbs(appPath) == false {
434
+	if !path.IsAbs(appPath) {
458 435
 		appPath = path.Join(curPath, appPath)
459 436
 	}
460 437
 
461 438
 	thePath, err := path.Abs(appPath)
462 439
 	if err != nil {
463
-		logger.Fatalf("Wrong application path: %s", thePath)
440
+		beeLogger.Log.Fatalf("Wrong application path: %s", thePath)
464 441
 	}
465
-	if stat, err := os.Stat(thePath); os.IsNotExist(err) || stat.IsDir() == false {
466
-		logger.Fatalf("Application path does not exist: %s", thePath)
442
+	if stat, err := os.Stat(thePath); os.IsNotExist(err) || !stat.IsDir() {
443
+		beeLogger.Log.Fatalf("Application path does not exist: %s", thePath)
467 444
 	}
468 445
 
469
-	logger.Infof("Packaging application on '%s'...", thePath)
446
+	beeLogger.Log.Infof("Packaging application on '%s'...", thePath)
470 447
 
471 448
 	appName := path.Base(thePath)
472 449
 
@@ -488,12 +465,12 @@ func packApp(cmd *Command, args []string) int {
488 465
 		// Remove the tmpdir once bee pack is done
489 466
 		err := os.RemoveAll(tmpdir)
490 467
 		if err != nil {
491
-			logger.Error("Failed to remove the generated temp dir")
468
+			beeLogger.Log.Error("Failed to remove the generated temp dir")
492 469
 		}
493 470
 	}()
494 471
 
495 472
 	if build {
496
-		logger.Info("Building application...")
473
+		beeLogger.Log.Info("Building application...")
497 474
 		var envs []string
498 475
 		for _, env := range buildEnvs {
499 476
 			parts := strings.SplitN(env, "=", 2)
@@ -515,7 +492,7 @@ func packApp(cmd *Command, args []string) int {
515 492
 		os.Setenv("GOOS", goos)
516 493
 		os.Setenv("GOARCH", goarch)
517 494
 
518
-		logger.Infof("Using: GOOS=%s GOARCH=%s", goos, goarch)
495
+		beeLogger.Log.Infof("Using: GOOS=%s GOARCH=%s", goos, goarch)
519 496
 
520 497
 		binPath := path.Join(tmpdir, appName)
521 498
 		if goos == "windows" {
@@ -538,10 +515,10 @@ func packApp(cmd *Command, args []string) int {
538 515
 		execmd.Dir = thePath
539 516
 		err = execmd.Run()
540 517
 		if err != nil {
541
-			logger.Fatal(err.Error())
518
+			beeLogger.Log.Fatal(err.Error())
542 519
 		}
543 520
 
544
-		logger.Success("Build Successful!")
521
+		beeLogger.Log.Success("Build Successful!")
545 522
 	}
546 523
 
547 524
 	switch format {
@@ -552,14 +529,14 @@ func packApp(cmd *Command, args []string) int {
552 529
 
553 530
 	outputN := appName + "." + format
554 531
 
555
-	if outputP == "" || path.IsAbs(outputP) == false {
532
+	if outputP == "" || !path.IsAbs(outputP) {
556 533
 		outputP = path.Join(curPath, outputP)
557 534
 	}
558 535
 
559 536
 	if _, err := os.Stat(outputP); err != nil {
560 537
 		err = os.MkdirAll(outputP, 0755)
561 538
 		if err != nil {
562
-			logger.Fatal(err.Error())
539
+			beeLogger.Log.Fatal(err.Error())
563 540
 		}
564 541
 	}
565 542
 
@@ -581,20 +558,20 @@ func packApp(cmd *Command, args []string) int {
581 558
 	for _, r := range excludeR {
582 559
 		if len(r) > 0 {
583 560
 			if re, err := regexp.Compile(r); err != nil {
584
-				logger.Fatal(err.Error())
561
+				beeLogger.Log.Fatal(err.Error())
585 562
 			} else {
586 563
 				exr = append(exr, re)
587 564
 			}
588 565
 		}
589 566
 	}
590 567
 
591
-	logger.Infof("Writing to output: %s", outputP)
568
+	beeLogger.Log.Infof("Writing to output: %s", outputP)
592 569
 
593 570
 	err = packDirectory(output, exp, exs, exr, tmpdir, thePath)
594 571
 	if err != nil {
595
-		logger.Fatal(err.Error())
572
+		beeLogger.Log.Fatal(err.Error())
596 573
 	}
597 574
 
598
-	logger.Success("Application packed!")
575
+	beeLogger.Log.Success("Application packed!")
599 576
 	return 0
600 577
 }

+ 88
- 0
cmd/commands/run/docs.go View File

@@ -0,0 +1,88 @@
1
+package run
2
+
3
+import (
4
+	"archive/zip"
5
+	"io"
6
+	"net/http"
7
+	"os"
8
+	"strings"
9
+
10
+	beeLogger "github.com/beego/bee/logger"
11
+)
12
+
13
+var (
14
+	swaggerVersion = "2"
15
+	swaggerlink    = "https://github.com/beego/swagger/archive/v" + swaggerVersion + ".zip"
16
+)
17
+
18
+func downloadFromURL(url, fileName string) {
19
+	var down bool
20
+	if fd, err := os.Stat(fileName); err != nil && os.IsNotExist(err) {
21
+		down = true
22
+	} else if fd.Size() == int64(0) {
23
+		down = true
24
+	} else {
25
+		beeLogger.Log.Infof("'%s' already exists", fileName)
26
+		return
27
+	}
28
+	if down {
29
+		beeLogger.Log.Infof("Downloading '%s' to '%s'...", url, fileName)
30
+		output, err := os.Create(fileName)
31
+		if err != nil {
32
+			beeLogger.Log.Errorf("Error while creating '%s': %s", fileName, err)
33
+			return
34
+		}
35
+		defer output.Close()
36
+
37
+		response, err := http.Get(url)
38
+		if err != nil {
39
+			beeLogger.Log.Errorf("Error while downloading '%s': %s", url, err)
40
+			return
41
+		}
42
+		defer response.Body.Close()
43
+
44
+		n, err := io.Copy(output, response.Body)
45
+		if err != nil {
46
+			beeLogger.Log.Errorf("Error while downloading '%s': %s", url, err)
47
+			return
48
+		}
49
+		beeLogger.Log.Successf("%d bytes downloaded!", n)
50
+	}
51
+}
52
+
53
+func unzipAndDelete(src string) error {
54
+	beeLogger.Log.Infof("Unzipping '%s'...", src)
55
+	r, err := zip.OpenReader(src)
56
+	if err != nil {
57
+		return err
58
+	}
59
+	defer r.Close()
60
+
61
+	rp := strings.NewReplacer("swagger-"+swaggerVersion, "swagger")
62
+	for _, f := range r.File {
63
+		rc, err := f.Open()
64
+		if err != nil {
65
+			return err
66
+		}
67
+		defer rc.Close()
68
+
69
+		fname := rp.Replace(f.Name)
70
+		if f.FileInfo().IsDir() {
71
+			os.MkdirAll(fname, f.Mode())
72
+		} else {
73
+			f, err := os.OpenFile(
74
+				fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
75
+			if err != nil {
76
+				return err
77
+			}
78
+			defer f.Close()
79
+
80
+			_, err = io.Copy(f, rc)
81
+			if err != nil {
82
+				return err
83
+			}
84
+		}
85
+	}
86
+	beeLogger.Log.Successf("Done! Deleting '%s'...", src)
87
+	return os.RemoveAll(src)
88
+}

reload.go → cmd/commands/run/reload.go View File

@@ -11,13 +11,14 @@
11 11
 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 12
 // License for the specific language governing permissions and limitations
13 13
 // under the License.
14
-package main
14
+package run
15 15
 
16 16
 import (
17 17
 	"bytes"
18 18
 	"net/http"
19 19
 	"time"
20 20
 
21
+	beeLogger "github.com/beego/bee/logger"
21 22
 	"github.com/gorilla/websocket"
22 23
 )
23 24
 
@@ -70,7 +71,7 @@ func (c *wsClient) readPump() {
70 71
 		_, _, err := c.conn.ReadMessage()
71 72
 		if err != nil {
72 73
 			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
73
-				logger.Errorf("An error happened when reading from the Websocket client: %v", err)