mirror of https://github.com/knative/func.git
164 lines
3.5 KiB
Go
164 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"archive/zip"
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
const templatesPath = "../../templates"
|
|
|
|
// This program generates zz_filesystem_generated.go file containing byte array variable named TemplatesZip.
|
|
// The variable contains zip of "./templates" directory.
|
|
func main() {
|
|
f, err := os.OpenFile("../../generate/zz_filesystem_generated.go", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer f.Close()
|
|
|
|
srcOut := bufio.NewWriter(f)
|
|
defer srcOut.Flush()
|
|
|
|
_, err = fmt.Fprintf(srcOut, "// Code generated by go generate; DO NOT EDIT.\npackage generate\n\nvar TemplatesZip = []byte{")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
zipWriter := zip.NewWriter(newGoByteArrayWriter(srcOut))
|
|
buff := make([]byte, 4*1024)
|
|
err = filepath.Walk(templatesPath, func(path string, info fs.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
name, err := filepath.Rel(templatesPath, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if name == "." {
|
|
return nil
|
|
}
|
|
name = filepath.ToSlash(name)
|
|
if info.IsDir() {
|
|
name = name + "/"
|
|
}
|
|
|
|
header := &zip.FileHeader{
|
|
Name: name,
|
|
Method: zip.Deflate,
|
|
}
|
|
|
|
// Coercing permission to 755 for directories/executables and to 644 for non-executable files.
|
|
// This is needed to ensure reproducible builds on machines with different values of `umask`.
|
|
var mode fs.FileMode
|
|
switch {
|
|
case info.Mode()&fs.ModeSymlink != 0:
|
|
mode = 0777 | fs.ModeSymlink
|
|
case info.IsDir() || (info.Mode().Perm()&0111) != 0: // dir or executable
|
|
mode = 0755
|
|
case info.Mode()&fs.ModeType == 0: // regular file
|
|
mode = 0644
|
|
default:
|
|
return fmt.Errorf("unsupported file type: %s", info.Mode().String())
|
|
}
|
|
header.SetMode(mode)
|
|
|
|
w, err := zipWriter.CreateHeader(header)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch {
|
|
case info.Mode()&fs.ModeSymlink != 0:
|
|
symlinkTarget, err := os.Readlink(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = w.Write([]byte(filepath.ToSlash(symlinkTarget)))
|
|
return err
|
|
case info.Mode()&fs.ModeType == 0: // regular file
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
_, err = io.CopyBuffer(w, f, buff)
|
|
return err
|
|
default:
|
|
return nil
|
|
}
|
|
})
|
|
zipWriter.Close()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
_, err = fmt.Fprint(srcOut, "\n}\n")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// goByteArrayWriter dumps bytes as a Go integer hex literals separated by commas into underlying Writer.
|
|
// Each line of the output will be indented by a tab and each line will contain at most 32 integer literals.
|
|
// This is useful when generating Go array literals.
|
|
type goByteArrayWriter struct {
|
|
i uint32
|
|
w io.Writer
|
|
hexDigitWithComma []byte
|
|
}
|
|
|
|
func newGoByteArrayWriter(w io.Writer) *goByteArrayWriter {
|
|
return &goByteArrayWriter{
|
|
i: 0,
|
|
w: w,
|
|
hexDigitWithComma: []byte("0x00,"),
|
|
}
|
|
}
|
|
|
|
var hexs = []byte("0123456789abcdef")
|
|
var space = []byte(" ")
|
|
var newLineAndTab = []byte("\n\t")
|
|
|
|
const bytesInLine = 32
|
|
|
|
func (g *goByteArrayWriter) Write(bs []byte) (written int, err error) {
|
|
for _, b := range bs {
|
|
if g.i == 0 {
|
|
_, err = g.w.Write(newLineAndTab)
|
|
if err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
_, err = g.w.Write(space)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
g.hexDigitWithComma[2] = hexs[b>>4]
|
|
g.hexDigitWithComma[3] = hexs[b&0x0f]
|
|
_, err = g.w.Write(g.hexDigitWithComma)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if g.i == bytesInLine-1 {
|
|
g.i = 0
|
|
} else {
|
|
g.i++
|
|
}
|
|
|
|
written += 1
|
|
}
|
|
|
|
return
|
|
}
|