bee pack add two args -exr (support exclude filename use regexp) -be (can add custom build env variables) #352 #1

This commit is contained in:
slene 2013-12-31 19:28:36 +08:00
parent 0844deda67
commit 89ed4f92e7
1 changed files with 118 additions and 38 deletions

144
pack.go
View File

@ -44,15 +44,17 @@ compress an beego project
-p app path. default is current path -p app path. default is current path
-b build specify platform app. default true -b build specify platform app. default true
-ba additional args of go build -ba additional args of go build
-be=[] additional ENV Variables of go build. eg: GOARCH=arm
-o compressed file output dir. default use current path -o compressed file output dir. default use current path
-f format. [ tar.gz / zip ]. default tar.gz. note: zip doesn't support embed symlink, skip it -f="" format. [ tar.gz / zip ]. default tar.gz. note: zip doesn't support embed symlink, skip it
-exp path exclude prefix. default: . -exp="" relpath exclude prefix. default: .
-exs path exclude suffix. default: .go:.DS_Store:.tmp -exs="" relpath exclude suffix. default: .go:.DS_Store:.tmp
all path use : as separator all path use : as separator
-fs follow symlink. default false -exr=[] file/directory name exclude by Regexp. default: ^.
-ss skip symlink. default false -fs=false follow symlink. default false
-ss=false skip symlink. default false
default embed symlink into compressed file default embed symlink into compressed file
-v verbose -v=false verbose
`, `,
} }
@ -61,26 +63,41 @@ var (
excludeP string excludeP string
excludeS string excludeS string
outputP string outputP string
excludeR ListOpts
fsym bool fsym bool
ssym bool ssym bool
build bool build bool
buildArgs string buildArgs string
buildEnvs ListOpts
verbose bool verbose bool
format string format string
) )
type ListOpts []string
func (opts *ListOpts) String() string {
return fmt.Sprint(*opts)
}
func (opts *ListOpts) Set(value string) error {
*opts = append(*opts, value)
return nil
}
func init() { func init() {
fs := flag.NewFlagSet("pack", flag.ContinueOnError) fs := flag.NewFlagSet("pack", flag.ContinueOnError)
fs.StringVar(&appPath, "p", "", "") fs.StringVar(&appPath, "p", "", "app path. default is current path")
fs.StringVar(&excludeP, "exp", ".", "") fs.BoolVar(&build, "b", true, "build specify platform app")
fs.StringVar(&excludeS, "exs", ".go:.DS_Store:.tmp", "") fs.StringVar(&buildArgs, "ba", "", "additional args of go build")
fs.StringVar(&outputP, "o", "", "") fs.Var(&buildEnvs, "be", "additional ENV Variables of go build. eg: GOARCH=arm")
fs.BoolVar(&build, "b", true, "") fs.StringVar(&outputP, "o", "", "compressed file output dir. default use current path")
fs.StringVar(&buildArgs, "ba", "", "") fs.StringVar(&format, "f", "tar.gz", "format. [ tar.gz / zip ] note: zip doesn't support embed symlink, skip it")
fs.BoolVar(&fsym, "fs", false, "") fs.StringVar(&excludeP, "exp", ".", "path exclude prefix. use : as separator")
fs.BoolVar(&ssym, "ss", false, "") fs.StringVar(&excludeS, "exs", ".go:.DS_Store:.tmp", "path exclude suffix. use : as separator")
fs.BoolVar(&verbose, "v", false, "") fs.Var(&excludeR, "exr", "filename exclude by Regexp")
fs.StringVar(&format, "f", "tar.gz", "") fs.BoolVar(&fsym, "fs", false, "follow symlink")
fs.BoolVar(&ssym, "ss", false, "skip symlink")
fs.BoolVar(&verbose, "v", false, "verbose")
cmdPack.Flag = *fs cmdPack.Flag = *fs
cmdPack.Run = packApp cmdPack.Run = packApp
} }
@ -109,6 +126,7 @@ type walkFileTree struct {
wak walker wak walker
prefix string prefix string
excludePrefix []string excludePrefix []string
excludeRegexp []*regexp.Regexp
excludeSuffix []string excludeSuffix []string
allfiles map[string]bool allfiles map[string]bool
} }
@ -117,32 +135,47 @@ func (wft *walkFileTree) setPrefix(prefix string) {
wft.prefix = prefix wft.prefix = prefix
} }
func (wft *walkFileTree) isExclude(name string) bool { func (wft *walkFileTree) isExclude(fPath string) bool {
if name == "" { if fPath == "" {
return true return true
} }
for _, prefix := range wft.excludePrefix { for _, prefix := range wft.excludePrefix {
if strings.HasPrefix(name, prefix) { if strings.HasPrefix(fPath, prefix) {
return true return true
} }
} }
for _, suffix := range wft.excludeSuffix { for _, suffix := range wft.excludeSuffix {
if strings.HasSuffix(name, suffix) { if strings.HasSuffix(fPath, suffix) {
return true return true
} }
} }
return false return false
} }
func (wft *walkFileTree) isExcludeName(name string) bool {
for _, r := range wft.excludeRegexp {
if r.MatchString(name) {
return true
}
}
return false
}
func (wft *walkFileTree) isEmpty(fpath string) bool { func (wft *walkFileTree) isEmpty(fpath string) bool {
fh, _ := os.Open(fpath) fh, _ := os.Open(fpath)
defer fh.Close() defer fh.Close()
infos, _ := fh.Readdir(-1) infos, _ := fh.Readdir(-1)
for _, fi := range infos { for _, fi := range infos {
fp := path.Join(fpath, fi.Name()) fn := fi.Name()
fp := path.Join(fpath, fn)
if wft.isExclude(wft.virPath(fp)) { if wft.isExclude(wft.virPath(fp)) {
continue continue
} }
if wft.isExcludeName(fn) {
continue
}
if fi.Mode()&os.ModeSymlink > 0 { if fi.Mode()&os.ModeSymlink > 0 {
continue continue
} }
@ -195,15 +228,12 @@ func (wft *walkFileTree) walkLeaf(fpath string, fi os.FileInfo, err error) error
return nil return nil
} }
name := wft.virPath(fpath)
if wft.isExclude(name) {
return nil
}
if ssym && fi.Mode()&os.ModeSymlink > 0 { if ssym && fi.Mode()&os.ModeSymlink > 0 {
return nil return nil
} }
name := wft.virPath(fpath)
if wft.allfiles[name] { if wft.allfiles[name] {
return nil return nil
} }
@ -229,6 +259,18 @@ func (wft *walkFileTree) iterDirectory(fpath string, fi os.FileInfo) error {
fi = nfi fi = nfi
} }
relPath := wft.virPath(fpath)
if len(relPath) > 0 {
if wft.isExcludeName(fi.Name()) {
return nil
}
if wft.isExclude(relPath) {
return nil
}
}
err := wft.walkLeaf(fpath, fi, nil) err := wft.walkLeaf(fpath, fi, nil)
if err != nil { if err != nil {
if fi.IsDir() && err == path.SkipDir { if fi.IsDir() && err == path.SkipDir {
@ -314,7 +356,7 @@ type zipWalk struct {
func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) { func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
isSym := fi.Mode()&os.ModeSymlink > 0 isSym := fi.Mode()&os.ModeSymlink > 0
if isSym { if isSym {
// golang1.1 doesn't support embed symlink // golang1.2 still not support embed symlink
// what i miss something? // what i miss something?
return false, nil return false, nil
} }
@ -346,9 +388,14 @@ func (wft *zipWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
return true, nil return true, nil
} }
func packDirectory(excludePrefix []string, excludeSuffix []string, includePath ...string) (err error) { func packDirectory(excludePrefix []string, excludeSuffix []string,
fmt.Printf("exclude prefix: %s\n", strings.Join(excludePrefix, ":")) excludeRegexp []*regexp.Regexp, includePath ...string) (err error) {
fmt.Printf("exclude suffix: %s\n", strings.Join(excludeSuffix, ":"))
fmt.Printf("exclude relpath prefix: %s\n", strings.Join(excludePrefix, ":"))
fmt.Printf("exclude relpath suffix: %s\n", strings.Join(excludeSuffix, ":"))
if len(excludeRegexp) > 0 {
fmt.Printf("exclude filename regex: `%s`\n", strings.Join(excludeR, "`, `"))
}
w, err := os.OpenFile(outputP, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) w, err := os.OpenFile(outputP, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil { if err != nil {
@ -368,6 +415,7 @@ func packDirectory(excludePrefix []string, excludeSuffix []string, includePath .
walk.wak = walk walk.wak = walk
walk.excludePrefix = excludePrefix walk.excludePrefix = excludePrefix
walk.excludeSuffix = excludeSuffix walk.excludeSuffix = excludeSuffix
walk.excludeRegexp = excludeRegexp
wft = walk wft = walk
} else { } else {
walk := new(tarWalk) walk := new(tarWalk)
@ -385,6 +433,7 @@ func packDirectory(excludePrefix []string, excludeSuffix []string, includePath .
walk.wak = walk walk.wak = walk
walk.excludePrefix = excludePrefix walk.excludePrefix = excludePrefix
walk.excludeSuffix = excludeSuffix walk.excludeSuffix = excludeSuffix
walk.excludeRegexp = excludeRegexp
wft = walk wft = walk
} }
@ -469,12 +518,31 @@ func packApp(cmd *Command, args []string) {
os.Mkdir(tmpdir, 0700) os.Mkdir(tmpdir, 0700)
if build { if build {
fmt.Println("GOOS", goos, "GOARCH", goarch)
fmt.Println("build", appName) fmt.Println("build", appName)
var envs []string
for _, env := range buildEnvs {
parts := strings.SplitN(env, "=", 2)
if len(parts) == 2 {
k, v := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
if len(k) > 0 && len(v) > 0 {
switch k {
case "GOOS":
goos = v
case "GOARCH":
goarch = v
default:
envs = append(envs, fmt.Sprintf("%s=%s", k, v))
}
}
}
}
os.Setenv("GOOS", goos) os.Setenv("GOOS", goos)
os.Setenv("GOARCH", goarch) os.Setenv("GOARCH", goarch)
fmt.Println("GOOS", goos, "GOARCH", goarch)
binPath := path.Join(tmpdir, appName) binPath := path.Join(tmpdir, appName)
if goos == "windows" { if goos == "windows" {
binPath += ".exe" binPath += ".exe"
@ -490,6 +558,7 @@ func packApp(cmd *Command, args []string) {
} }
execmd := exec.Command(gobin, args...) execmd := exec.Command(gobin, args...)
execmd.Env = append(os.Environ(), envs...)
execmd.Stdout = os.Stdout execmd.Stdout = os.Stdout
execmd.Stderr = os.Stderr execmd.Stderr = os.Stderr
execmd.Dir = thePath execmd.Dir = thePath
@ -534,7 +603,18 @@ func packApp(cmd *Command, args []string) {
} }
} }
err = packDirectory(exp, exs, tmpdir, thePath) var exr []*regexp.Regexp
for _, r := range excludeR {
if len(r) > 0 {
if re, err := regexp.Compile(r); err != nil {
exitPrint(err.Error())
} else {
exr = append(exr, re)
}
}
}
err = packDirectory(exp, exs, exr, tmpdir, thePath)
if err != nil { if err != nil {
exitPrint(err.Error()) exitPrint(err.Error())
} }