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

156
pack.go
View File

@ -41,18 +41,20 @@ var cmdPack = &Command{
Long: ` Long: `
compress an beego project 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
-o compressed file output dir. default use current path -be=[] additional ENV Variables of go build. eg: GOARCH=arm
-f format. [ tar.gz / zip ]. default tar.gz. note: zip doesn't support embed symlink, skip it -o compressed file output dir. default use current path
-exp path exclude prefix. default: . -f="" format. [ tar.gz / zip ]. default tar.gz. note: zip doesn't support embed symlink, skip it
-exs path exclude suffix. default: .go:.DS_Store:.tmp -exp="" relpath exclude prefix. default: .
all path use : as separator -exs="" relpath exclude suffix. default: .go:.DS_Store:.tmp
-fs follow symlink. default false all path use : as separator
-ss skip symlink. default false -exr=[] file/directory name exclude by Regexp. default: ^.
default embed symlink into compressed file -fs=false follow symlink. default false
-v verbose -ss=false skip symlink. default false
default embed symlink into compressed file
-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())
} }