forked from revel/revel
/
new.go
151 lines (128 loc) · 3.43 KB
/
new.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"fmt"
"go/build"
"io/ioutil"
"math/rand"
"os"
"path"
"path/filepath"
"strings"
"text/template"
)
var cmdNew = &Command{
UsageLine: "new [path]",
Short: "create a skeleton Revel application",
Long: `~
~ New creates a few files to get a new Revel application running quickly.
~
~ It puts all of the files in the given directory, taking the final element in
~ the path to be the app name.
~
~ For example:
~ rev new github.com/robfig/chatapp`,
}
func init() {
cmdNew.Run = newApp
}
var (
appDir string
skeletonBase string
)
func newApp(args []string) {
if len(args) == 0 {
errorf("~ No path given.\nRun 'rev help new' for usage.\n")
}
_, err := os.Open(args[0])
if err == nil {
fmt.Fprintf(os.Stderr, "~ Abort: Directory %s already exists.\n", args[0])
return
}
revelPkg, err := build.Import("github.com/robfig/revel", "", build.FindOnly)
if err != nil {
fmt.Fprintln(os.Stderr, "~ Failed to find revel code.")
return
}
err = os.MkdirAll(args[0], 0777)
if err != nil {
fmt.Fprintln(os.Stderr, "~ Abort: Failed to create directory:", err)
return
}
skeletonBase = path.Join(revelPkg.Dir, "skeleton")
appDir, err = filepath.Abs(args[0])
if err != nil {
fmt.Fprintln(os.Stderr, "~ Abort: Failed to get absolute directory:", err)
return
}
err = filepath.Walk(skeletonBase, copySkeleton)
if err != nil {
fmt.Fprintln(os.Stderr, "~ Failed to copy skeleton:", err)
}
fmt.Fprintln(os.Stdout, "~ Your application is ready:\n~ ", appDir)
}
// copySkeleton copies the skeleton app tree over to a new directory.
func copySkeleton(skelPath string, skelInfo os.FileInfo, err error) error {
// Get the relative path from the skeleton base, and the corresponding path in
// the app directory.
relSkelPath := strings.TrimLeft(skelPath[len(skeletonBase):], string(os.PathSeparator))
appFile := path.Join(appDir, relSkelPath)
if len(relSkelPath) == 0 {
return nil
}
// Create a subdirectory if necessary.
if skelInfo.IsDir() {
err := os.Mkdir(path.Join(appDir, relSkelPath), 0777)
if err != nil {
fmt.Fprintln(os.Stderr, "~ Failed to create directory:", err)
return err
}
return nil
}
// If this is app.conf, we have to render it as a template.
if relSkelPath == "conf/app.conf" {
tmpl, err := template.ParseFiles(skelPath)
if err != nil || tmpl == nil {
fmt.Fprintln(os.Stderr, "Failed to parse skeleton app.conf as a template:", err)
return err
}
f, err := os.Create(appFile)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to create app.conf:", err)
return err
}
err = tmpl.Execute(f, map[string]string{
"AppName": filepath.Base(appDir),
"Secret": genSecret(),
})
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to render template:", err)
return err
}
err = f.Close()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to close app.conf:", err)
return err
}
return nil
}
// Copy over the files.
skelBytes, err := ioutil.ReadFile(skelPath)
if err != nil {
fmt.Fprintln(os.Stderr, "~ Failed to read file:", err)
return err
}
err = ioutil.WriteFile(appFile, skelBytes, 0666)
if err != nil {
fmt.Fprintln(os.Stderr, "~ Failed to write file:", err)
return err
}
return nil
}
const alphaNumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
func genSecret() string {
chars := make([]byte, 64)
for i := 0; i < 64; i++ {
chars[i] = alphaNumeric[rand.Intn(len(alphaNumeric))]
}
return string(chars)
}