blob: f55b6fbb729718830776d66927421e8fff434636 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 main
import (
"bytes"
"context"
"fmt"
"go/format"
"io"
"math"
"path/filepath"
"sort"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/app"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/app/appcmd"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage/storageos"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const (
programName = "storage-go-data"
pkgFlagName = "package"
sliceLength = math.MaxInt64
)
func main() {
appcmd.Main(context.Background(), newCommand())
}
func newCommand() *appcmd.Command {
flags := newFlags()
return &appcmd.Command{
Use: fmt.Sprintf("%s path/to/dir", programName),
Args: cobra.ExactArgs(1),
Run: func(ctx context.Context, container app.Container) error {
return run(ctx, container, flags)
},
BindFlags: flags.Bind,
}
}
type flags struct {
Pkg string
}
func newFlags() *flags {
return &flags{}
}
func (f *flags) Bind(flagSet *pflag.FlagSet) {
flagSet.StringVar(
&f.Pkg,
pkgFlagName,
"",
"The name of the generated package.",
)
}
func run(ctx context.Context, container app.Container, flags *flags) error {
dirPath := container.Arg(0)
packageName := flags.Pkg
if packageName == "" {
packageName = filepath.Base(dirPath)
}
pathToData, err := getPathToData(ctx, dirPath)
if err != nil {
return err
}
golangFileData, err := getGolangFileData(pathToData, packageName)
if err != nil {
return err
}
_, err = container.Stdout().Write(golangFileData)
return err
}
func getPathToData(ctx context.Context, dirPath string) (map[string][]byte, error) {
readWriteBucket, err := storageos.NewProvider(storageos.ProviderWithSymlinks()).NewReadWriteBucket(dirPath)
if err != nil {
return nil, err
}
pathToData := make(map[string][]byte)
if err := storage.WalkReadObjects(
ctx,
readWriteBucket,
"",
func(readObject storage.ReadObject) error {
data, err := io.ReadAll(readObject)
if err != nil {
return err
}
pathToData[readObject.Path()] = data
return nil
},
); err != nil {
return nil, err
}
return pathToData, nil
}
func getGolangFileData(pathToData map[string][]byte, packageName string) ([]byte, error) {
buffer := bytes.NewBuffer(nil)
_, _ = buffer.WriteString(`// Code generated by `)
_, _ = buffer.WriteString(programName)
_, _ = buffer.WriteString(`. DO NOT EDIT.
package `)
_, _ = buffer.WriteString(packageName)
_, _ = buffer.WriteString(`
import (
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage/storagemem"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/normalpath"
)
var (
// ReadBucket is the storage.ReadBucket with the static data generated for this package.
ReadBucket storage.ReadBucket
pathToData = map[string][]byte{
`)
paths := make([]string, 0, len(pathToData))
for path := range pathToData {
paths = append(paths, path)
}
sort.Strings(paths)
for _, path := range paths {
_, _ = buffer.WriteString(`"`)
_, _ = buffer.WriteString(path)
_, _ = buffer.WriteString(`": {
`)
data := pathToData[path]
for len(data) > 0 {
n := sliceLength
if n > len(data) {
n = len(data)
}
accum := ""
for _, elem := range data[:n] {
accum += fmt.Sprintf("0x%02x,", elem)
}
_, _ = buffer.WriteString(accum)
_, _ = buffer.WriteString("\n")
data = data[n:]
}
_, _ = buffer.WriteString(`},
`)
}
_, _ = buffer.WriteString(`}
)
func init() {
readBucket, err := storagemem.NewReadBucket(pathToData)
if err != nil {
panic(err.Error())
}
ReadBucket = readBucket
}
// Exists returns true if the given path exists in the static data.
//
// The path is normalized within this function.
func Exists(path string) bool {
_, ok := pathToData[normalpath.Normalize(path)]
return ok
}
`)
return format.Source(buffer.Bytes())
}