mirror of
https://github.com/beego/bee.git
synced 2024-11-26 11:31:29 +00:00
c538bfbc8f
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
252 lines
5.2 KiB
Go
252 lines
5.2 KiB
Go
// Copyright 2013 bee authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
// not use this file except in compliance with the License. You may obtain
|
|
// a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package bale
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/beego/bee/cmd/commands"
|
|
"github.com/beego/bee/cmd/commands/version"
|
|
"github.com/beego/bee/config"
|
|
beeLogger "github.com/beego/bee/logger"
|
|
"github.com/beego/bee/utils"
|
|
)
|
|
|
|
var CmdBale = &commands.Command{
|
|
UsageLine: "bale",
|
|
Short: "Transforms non-Go files to Go source files",
|
|
Long: `Bale command compress all the static files in to a single binary file.
|
|
|
|
This is useful to not have to carry static files including js, css, images and
|
|
views when deploying a Web application.
|
|
|
|
It will auto-generate an unpack function to the main package then run it during the runtime.
|
|
This is mainly used for zealots who are requiring 100% Go code.
|
|
`,
|
|
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
|
Run: runBale,
|
|
}
|
|
|
|
func init() {
|
|
commands.AvailableCommands = append(commands.AvailableCommands, CmdBale)
|
|
}
|
|
|
|
func runBale(cmd *commands.Command, args []string) int {
|
|
os.RemoveAll("bale")
|
|
os.Mkdir("bale", os.ModePerm)
|
|
|
|
// Pack and compress data
|
|
for _, p := range config.Conf.Bale.Dirs {
|
|
if !utils.IsExist(p) {
|
|
beeLogger.Log.Warnf("Skipped directory: %s", p)
|
|
continue
|
|
}
|
|
beeLogger.Log.Infof("Packaging directory: %s", p)
|
|
filepath.Walk(p, walkFn)
|
|
}
|
|
|
|
// Generate auto-uncompress function.
|
|
buf := new(bytes.Buffer)
|
|
buf.WriteString(fmt.Sprintf(BaleHeader, config.Conf.Bale.Import,
|
|
strings.Join(resFiles, "\",\n\t\t\""),
|
|
strings.Join(resFiles, ",\n\t\tbale.R")))
|
|
|
|
fw, err := os.Create("bale.go")
|
|
if err != nil {
|
|
beeLogger.Log.Fatalf("Failed to create file: %s", err)
|
|
}
|
|
defer fw.Close()
|
|
|
|
_, err = fw.Write(buf.Bytes())
|
|
if err != nil {
|
|
beeLogger.Log.Fatalf("Failed to write data: %s", err)
|
|
}
|
|
|
|
beeLogger.Log.Success("Baled resources successfully!")
|
|
return 0
|
|
}
|
|
|
|
const (
|
|
// BaleHeader ...
|
|
BaleHeader = `package main
|
|
|
|
import(
|
|
"os"
|
|
"strings"
|
|
"path"
|
|
|
|
"%s"
|
|
)
|
|
|
|
func isExist(path string) bool {
|
|
_, err := os.Stat(path)
|
|
return err == nil || os.IsExist(err)
|
|
}
|
|
|
|
func init() {
|
|
files := []string{
|
|
"%s",
|
|
}
|
|
|
|
funcs := []func() []byte{
|
|
bale.R%s,
|
|
}
|
|
|
|
for i, f := range funcs {
|
|
fp := getFilePath(files[i])
|
|
if !isExist(fp) {
|
|
saveFile(fp, f())
|
|
}
|
|
}
|
|
}
|
|
|
|
func getFilePath(name string) string {
|
|
name = strings.Replace(name, "_4_", "/", -1)
|
|
name = strings.Replace(name, "_3_", " ", -1)
|
|
name = strings.Replace(name, "_2_", "-", -1)
|
|
name = strings.Replace(name, "_1_", ".", -1)
|
|
name = strings.Replace(name, "_0_", "_", -1)
|
|
return name
|
|
}
|
|
|
|
func saveFile(filePath string, b []byte) (int, error) {
|
|
os.MkdirAll(path.Dir(filePath), os.ModePerm)
|
|
fw, err := os.Create(filePath)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer fw.Close()
|
|
return fw.Write(b)
|
|
}
|
|
`
|
|
)
|
|
|
|
var resFiles = make([]string, 0, 10)
|
|
|
|
func walkFn(resPath string, info os.FileInfo, err error) error {
|
|
if info.IsDir() || filterSuffix(resPath) {
|
|
return nil
|
|
}
|
|
|
|
// Open resource files
|
|
fr, err := os.Open(resPath)
|
|
if err != nil {
|
|
beeLogger.Log.Fatalf("Failed to read file: %s", err)
|
|
}
|
|
|
|
// Convert path
|
|
resPath = strings.Replace(resPath, "_", "_0_", -1)
|
|
resPath = strings.Replace(resPath, ".", "_1_", -1)
|
|
resPath = strings.Replace(resPath, "-", "_2_", -1)
|
|
resPath = strings.Replace(resPath, " ", "_3_", -1)
|
|
sep := "/"
|
|
if runtime.GOOS == "windows" {
|
|
sep = "\\"
|
|
}
|
|
resPath = strings.Replace(resPath, sep, "_4_", -1)
|
|
|
|
// Create corresponding Go source files
|
|
os.MkdirAll(path.Dir(resPath), os.ModePerm)
|
|
fw, err := os.Create("bale/" + resPath + ".go")
|
|
if err != nil {
|
|
beeLogger.Log.Fatalf("Failed to create file: %s", err)
|
|
}
|
|
defer fw.Close()
|
|
|
|
// Write header
|
|
fmt.Fprintf(fw, Header, resPath)
|
|
|
|
// Copy and compress data
|
|
gz := gzip.NewWriter(&ByteWriter{Writer: fw})
|
|
io.Copy(gz, fr)
|
|
gz.Close()
|
|
|
|
// Write footer.
|
|
fmt.Fprint(fw, Footer)
|
|
|
|
resFiles = append(resFiles, resPath)
|
|
return nil
|
|
}
|
|
|
|
func filterSuffix(name string) bool {
|
|
for _, s := range config.Conf.Bale.IngExt {
|
|
if strings.HasSuffix(name, s) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
const (
|
|
// Header ...
|
|
Header = `package bale
|
|
|
|
import(
|
|
"bytes"
|
|
"compress/gzip"
|
|
"io"
|
|
)
|
|
|
|
func R%s() []byte {
|
|
gz, err := gzip.NewReader(bytes.NewBuffer([]byte{`
|
|
// Footer ...
|
|
Footer = `
|
|
}))
|
|
|
|
if err != nil {
|
|
panic("Unpack resources failed: " + err.Error())
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
io.Copy(&b, gz)
|
|
gz.Close()
|
|
|
|
return b.Bytes()
|
|
}`
|
|
)
|
|
|
|
var newline = []byte{'\n'}
|
|
|
|
// ByteWriter ...
|
|
type ByteWriter struct {
|
|
io.Writer
|
|
c int
|
|
}
|
|
|
|
func (w *ByteWriter) Write(p []byte) (n int, err error) {
|
|
if len(p) == 0 {
|
|
return
|
|
}
|
|
|
|
for n = range p {
|
|
if w.c%12 == 0 {
|
|
w.Writer.Write(newline)
|
|
w.c = 0
|
|
}
|
|
fmt.Fprintf(w.Writer, "0x%02x,", p[n])
|
|
w.c++
|
|
}
|
|
n++
|
|
return
|
|
}
|