/
helpers.go
177 lines (146 loc) · 4.41 KB
/
helpers.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Package helpers provide various convenience functions.
package helpers
import (
"bytes"
"crypto/rand"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"os/user"
"path/filepath"
"strings"
"github.com/kardianos/osext"
"github.com/mitchellh/go-homedir"
)
// GetGoPaths returns the GOPATH as an array of paths
func GoPaths() []string {
return strings.Split(os.Getenv("GOPATH"), ":")
}
// IsValidGoPath checks if a path is part of the GOPATH
func IsValidGoPath(gopath string) bool {
for _, part := range GoPaths() {
if gopath == part {
return true
}
}
return false
}
// GetProjectTemplateDir returns the path to go-bootstrap's project-templates/ directory
func GetProjectTemplateDir(projectTemplate string) (string, error) {
executableDir, err := osext.ExecutableFolder()
ExitOnError(err, "Cannot find go-bootstrap path")
ret := filepath.Join(executableDir, "project-templates", projectTemplate)
if _, err = os.Stat(ret); err == nil {
return ret, nil
}
base := filepath.Join("src", "github.com", "go-bootstrap", "go-bootstrap")
// if the project directory can't be found in the executable's dir,
// try to locate the source code, it should be there.
// $gopath/bin/../src/github.com/go-bootstrap/go-bootstrap
srcDir := filepath.Join(filepath.Dir(executableDir), base)
ret = filepath.Join(srcDir, "project-templates", projectTemplate)
if _, err = os.Stat(ret); err == nil {
return ret, nil
}
// As the last resort search all gopaths.
// This is useful when executed with `go run`
for _, gopath := range GoPaths() {
ret = filepath.Join(filepath.Join(gopath, base), "project-templates", projectTemplate)
if _, err = os.Stat(ret); err == nil {
return ret, nil
}
}
return "", errors.New(fmt.Sprintf("Unable to find go-bootstrap's %v directory", projectTemplate))
}
// BashEscape escapes various characters in bash environment.
func BashEscape(in string) string {
return strings.Replace(in, "&", `\&`, -1)
}
// RandString generates random string given n length.
func RandString(n int) string {
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
var randBytes = make([]byte, n)
rand.Read(randBytes)
for i, b := range randBytes {
randBytes[i] = letters[b%byte(len(letters))]
}
return string(randBytes)
}
// RecursiveSearchReplaceFiles find and replace various strings defined in replacers.
func RecursiveSearchReplaceFiles(fullpath string, replacers map[string]string) error {
fileOrDirList := []string{}
err := filepath.Walk(fullpath, func(path string, f os.FileInfo, err error) error {
fileOrDirList = append(fileOrDirList, path)
return nil
})
if err != nil {
return err
}
for _, fileOrDir := range fileOrDirList {
fileInfo, _ := os.Stat(fileOrDir)
if !fileInfo.IsDir() {
for oldString, newString := range replacers {
contentBytes, _ := ioutil.ReadFile(fileOrDir)
newContentBytes := bytes.Replace(contentBytes, []byte(oldString), []byte(newString), -1)
err := ioutil.WriteFile(fileOrDir, newContentBytes, fileInfo.Mode())
if err != nil {
return err
}
}
}
}
return nil
}
// DefaultPGDSN generates default PostgreSQL DSN path.
func DefaultPGDSN(dbName string) string {
// Start by checking environment variables.
pguser, pgpass, pghost, pgport, pgsslmode := os.Getenv("PGUSER"), os.Getenv("PGPASSWORD"), os.Getenv("PGHOST"), os.Getenv("PGPORT"), os.Getenv("PGSSLMODE")
hostPortSeparator := ":"
if pguser == "" {
pguser = GetCurrentUser()
}
isUnixDomainSocket := strings.HasPrefix(pghost, "/")
if isUnixDomainSocket {
hostPortSeparator = "/"
}
if pghost == "" {
pghost = "localhost"
}
if pgport == "" {
pgport = "5432"
}
if pgsslmode == "" {
pgsslmode = "disable"
}
dsn := fmt.Sprintf("postgres://%v@%v%v%v/%v?sslmode=%v", pguser, pghost, hostPortSeparator, pgport, dbName, pgsslmode)
if pgpass != "" {
dsn = dsn + "&password=" + pgpass
}
return dsn
}
// ExitOnError logs error message in fatal mode.
func ExitOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s\n%s", msg, err.Error())
}
}
// GetCurrentUser returns the username of the current user.
func GetCurrentUser() string {
currentUser, err := user.Current()
if err == nil {
return currentUser.Username
} else {
username, err := homedir.Dir()
if err == nil {
return username
} else {
osUsername := os.Getenv("USERNAME")
if osUsername == "" {
log.Fatalln("Cannot determine current user's username")
}
return osUsername
}
}
}