You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2023/06/02 07:39:10 UTC

[camel-k] branch main updated: chore(deps): revert vfs-gen removal

This is an automated email from the ASF dual-hosted git repository.

pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/main by this push:
     new 4a74b39be chore(deps): revert vfs-gen removal
4a74b39be is described below

commit 4a74b39be50c2fabe08e48f36c38574119d632f2
Author: Gaelle Fournier <ga...@gmail.com>
AuthorDate: Thu Jun 1 15:15:32 2023 +0200

    chore(deps): revert vfs-gen removal
    
    Ref #4326
---
 cmd/manager/main.go                  |   1 +
 cmd/util/vfs-gen/main.go             | 259 +++++++++++++++++++++++++++++++++++
 cmd/util/vfs-gen/multifs/multidir.go | 171 +++++++++++++++++++++++
 go.mod                               |   2 +
 go.sum                               |   4 +
 pkg/resources/resources_support.go   |   4 +
 6 files changed, 441 insertions(+)

diff --git a/cmd/manager/main.go b/cmd/manager/main.go
new file mode 120000
index 000000000..8413b53c5
--- /dev/null
+++ b/cmd/manager/main.go
@@ -0,0 +1 @@
+../kamel/main.go
\ No newline at end of file
diff --git a/cmd/util/vfs-gen/main.go b/cmd/util/vfs-gen/main.go
new file mode 100644
index 000000000..79d6f8593
--- /dev/null
+++ b/cmd/util/vfs-gen/main.go
@@ -0,0 +1,259 @@
+/*
+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 (
+	"flag"
+	"fmt"
+	"log"
+	"net/http"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"github.com/apache/camel-k/v2/pkg/util"
+
+	"github.com/apache/camel-k/v2/cmd/util/vfs-gen/multifs"
+	"github.com/apache/camel-k/v2/pkg/base"
+	"github.com/shurcooL/httpfs/filter"
+	"github.com/shurcooL/vfsgen"
+)
+
+func main() {
+	var rootDir string
+	var destDir string
+
+	wd, err := os.Getwd()
+	if err != nil {
+		log.Fatalln(err)
+	}
+
+	flag.StringVar(&rootDir, "root", base.GoModDirectory, "The absolute path from were the directories can be found (camel-k module directory by default)")
+	flag.StringVar(&destDir, "dest", wd, "The destination directory of the generated file (working directory by default)")
+	flag.Parse()
+
+	if len(flag.Args()) < 1 {
+		println("usage: vfs-gen [-root <absolute root parent path>] [-dest <directory>] directory1 [directory2 ... ...]")
+		os.Exit(1)
+	}
+
+	err = checkDir(rootDir)
+	if err != nil {
+		log.Fatalln(err)
+	}
+
+	dirNames := flag.Args()
+	for _, dirName := range dirNames {
+		absDir := filepath.Join(rootDir, dirName)
+		err := checkDir(absDir)
+		if err != nil {
+			log.Fatalln(err)
+		}
+	}
+
+	exclusions := calcExclusions(rootDir, dirNames)
+
+	//
+	// Destination file for the generated resources
+	//
+	resourceFile := path.Join(destDir, "resources.go")
+
+	mfs, err := multifs.New(rootDir, dirNames, exclusions)
+	if err != nil {
+		log.Fatalln(err)
+	}
+
+	var fs http.FileSystem = modTimeFS{
+		fs: mfs,
+	}
+
+	//
+	// Filter un-interesting files
+	//
+	fs = filter.Skip(fs, filter.FilesWithExtensions(".go"))
+	fs = filter.Skip(fs, func(path string, fi os.FileInfo) bool {
+		return strings.HasSuffix(path, ".gen.yaml") || strings.HasSuffix(path, ".gen.json")
+	})
+	fs = filter.Skip(fs, NamedFilesFilter("kustomization.yaml"))
+	fs = filter.Skip(fs, NamedFilesFilter("Makefile"))
+	fs = filter.Skip(fs, NamedFilesFilter("auto-generated.txt"))
+	fs = filter.Skip(fs, BigFilesFilter(1048576)) // 1M
+	fs = filter.Skip(fs, func(path string, fi os.FileInfo) bool {
+		for _, ex := range exclusions {
+			if strings.HasPrefix(path, ex) {
+				return true
+			}
+		}
+		return false
+	})
+
+	//
+	// Generate the assets
+	//
+	err = vfsgen.Generate(fs, vfsgen.Options{
+		Filename:    resourceFile,
+		PackageName: filepath.Base(destDir),
+	})
+	if err != nil {
+		log.Fatalln(err)
+	}
+
+	//
+	// Post-process the final resource file
+	//
+	header := `/*
+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.
+*/
+
+`
+	content, err := util.ReadFile(resourceFile)
+	if err != nil {
+		log.Fatalln(err)
+	}
+	var finalContent []byte
+	finalContent = append(finalContent, []byte(header)...)
+	finalContent = append(finalContent, content...)
+	if err := os.WriteFile(resourceFile, finalContent, 0o600); err != nil {
+		log.Fatalln(err)
+	}
+}
+
+func NamedFilesFilter(names ...string) func(path string, fi os.FileInfo) bool {
+	return func(path string, fi os.FileInfo) bool {
+		if fi.IsDir() {
+			return false
+		}
+
+		for _, name := range names {
+			if name == filepath.Base(path) {
+				return true
+			}
+		}
+
+		return false
+	}
+}
+
+//
+// If file is bigger than maximum size (in bytes) then exclude.
+//
+func BigFilesFilter(size int) func(path string, fi os.FileInfo) bool {
+	return func(path string, fi os.FileInfo) bool {
+		if fi.IsDir() {
+			return false
+		}
+
+		if fi.Size() > int64(size) {
+			log.Printf("Warning: File %s is skipped due to being %d bytes (greater than maximum %d bytes)", path, fi.Size(), size)
+			return true
+		}
+
+		return false
+	}
+}
+
+func calcExclusions(root string, dirNames []string) []string {
+	var exclusions []string
+
+	for _, name := range dirNames {
+		dirName := filepath.Join(root, name)
+		if err := filepath.Walk(dirName, func(resPath string, info os.FileInfo, err error) error {
+			if info.IsDir() {
+				ignoreFileName := path.Join(resPath, ".vfsignore")
+				_, err := os.Stat(ignoreFileName)
+				if err == nil {
+					rel, err := filepath.Rel(dirName, resPath)
+					if err != nil {
+						log.Fatalln(err)
+					}
+					if !strings.HasPrefix(rel, "/") {
+						rel = "/" + rel
+					}
+					exclusions = append(exclusions, rel)
+				} else if !os.IsNotExist(err) {
+					log.Fatalln(err)
+				}
+			}
+			return nil
+		}); err != nil {
+			log.Fatalln(err)
+		}
+	}
+
+	return exclusions
+}
+
+func checkDir(dirName string) error {
+	dir, err := os.Stat(dirName)
+	if err != nil {
+		return err
+	}
+	if !dir.IsDir() {
+		return fmt.Errorf("path %s is not a directory", dirName)
+	}
+
+	return nil
+}
+
+// modTimeFS wraps http.FileSystem to set mod time to 0 for all files.
+type modTimeFS struct {
+	fs http.FileSystem
+}
+
+func (fs modTimeFS) Open(name string) (http.File, error) {
+	f, err := fs.fs.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	return modTimeFile{f}, nil
+}
+
+type modTimeFile struct {
+	http.File
+}
+
+func (f modTimeFile) Stat() (os.FileInfo, error) {
+	fi, err := f.File.Stat()
+	if err != nil {
+		return nil, err
+	}
+	return modTimeFileInfo{fi}, nil
+}
+
+type modTimeFileInfo struct {
+	os.FileInfo
+}
+
+func (modTimeFileInfo) ModTime() time.Time {
+	return time.Time{}
+}
diff --git a/cmd/util/vfs-gen/multifs/multidir.go b/cmd/util/vfs-gen/multifs/multidir.go
new file mode 100644
index 000000000..7a7f62309
--- /dev/null
+++ b/cmd/util/vfs-gen/multifs/multidir.go
@@ -0,0 +1,171 @@
+/*
+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.
+*/
+
+/*
+Based on the union fs function available at
+https://github.com/shurcooL/httpfs/blob/master/union/union.go
+(Licenced under MIT)
+*/
+
+package multifs
+
+import (
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"github.com/shurcooL/httpfs/vfsutil"
+)
+
+func New(rootDir string, dirNames []string, exclude []string) (http.FileSystem, error) {
+	m := &multiFS{
+		rootDir: rootDir,
+		exclude: exclude,
+		mfs:     make(map[string]http.FileSystem),
+		root: &dirInfo{
+			name: "/",
+		},
+	}
+	for _, dirName := range dirNames {
+		err := m.bind(dirName)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return m, nil
+}
+
+type multiFS struct {
+	rootDir string
+	exclude []string
+	mfs     map[string]http.FileSystem
+	root    *dirInfo
+}
+
+func (m *multiFS) bind(dirName string) error {
+	absDir := filepath.Join(m.rootDir, dirName)
+
+	hfs := http.Dir(absDir)
+	m.mfs["/"+dirName] = hfs
+
+	//
+	// The 1-level down paths are needed since the
+	// remainder are covered by the http filesystems
+	//
+	fileInfos, err := vfsutil.ReadDir(hfs, "/")
+	if err != nil {
+		return err
+	}
+
+	for _, nfo := range fileInfos {
+		path := "/" + nfo.Name()
+
+		if m.excluded(path) {
+			continue // skip
+		}
+
+		if nfo.IsDir() {
+			m.root.entries = append(m.root.entries, &dirInfo{
+				name: path,
+			})
+		} else {
+			m.root.entries = append(m.root.entries, nfo)
+		}
+	}
+
+	return nil
+}
+
+func (m *multiFS) excluded(path string) bool {
+	for _, ex := range m.exclude {
+		if strings.HasPrefix(path, ex) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (m *multiFS) Open(path string) (http.File, error) {
+	if path == "/" {
+		return &dir{
+			dirInfo: m.root,
+		}, nil
+	}
+
+	for _, fs := range m.mfs {
+		f, err := fs.Open(path)
+		if err != nil {
+			continue
+		}
+
+		return f, nil
+	}
+
+	return nil, &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist}
+}
+
+// dirInfo is a static definition of a directory.
+type dirInfo struct {
+	name    string
+	entries []os.FileInfo
+}
+
+func (d *dirInfo) Read([]byte) (int, error) {
+	return 0, fmt.Errorf("cannot Read from directory %s", d.name)
+}
+func (d *dirInfo) Close() error               { return nil }
+func (d *dirInfo) Stat() (os.FileInfo, error) { return d, nil }
+
+func (d *dirInfo) Name() string       { return d.name }
+func (d *dirInfo) Size() int64        { return 0 }
+func (d *dirInfo) Mode() os.FileMode  { return 0o755 | os.ModeDir }
+func (d *dirInfo) ModTime() time.Time { return time.Time{} } // Actual mod time is not computed because it's expensive and rarely needed.
+func (d *dirInfo) IsDir() bool        { return true }
+func (d *dirInfo) Sys() interface{}   { return nil }
+
+// dir is an opened dir instance.
+type dir struct {
+	*dirInfo
+	pos int // Position within entries for Seek and Readdir.
+}
+
+func (d *dir) Seek(offset int64, whence int) (int64, error) {
+	if offset == 0 && whence == io.SeekStart {
+		d.pos = 0
+		return 0, nil
+	}
+	return 0, fmt.Errorf("unsupported Seek in directory %s", d.dirInfo.name)
+}
+
+func (d *dir) Readdir(count int) ([]os.FileInfo, error) {
+	if d.pos >= len(d.dirInfo.entries) && count > 0 {
+		return nil, io.EOF
+	}
+	if count <= 0 || count > len(d.dirInfo.entries)-d.pos {
+		count = len(d.dirInfo.entries) - d.pos
+	}
+	e := d.dirInfo.entries[d.pos : d.pos+count]
+	d.pos += count
+
+	return e, nil
+}
diff --git a/go.mod b/go.mod
index b871dd193..99eb45a35 100644
--- a/go.mod
+++ b/go.mod
@@ -30,6 +30,8 @@ require (
 	github.com/redhat-developer/service-binding-operator v1.3.4
 	github.com/rs/xid v1.5.0
 	github.com/scylladb/go-set v1.0.2
+	github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
+	github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
 	github.com/sirupsen/logrus v1.9.2
 	github.com/spf13/cobra v1.7.0
 	github.com/spf13/pflag v1.0.5
diff --git a/go.sum b/go.sum
index 883aa0ffd..3fbb9d949 100644
--- a/go.sum
+++ b/go.sum
@@ -630,7 +630,11 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
 github.com/scylladb/go-set v1.0.2 h1:SkvlMCKhP0wyyct6j+0IHJkBkSZL+TDzZ4E7f7BCcRE=
 github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
+github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0=
+github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
diff --git a/pkg/resources/resources_support.go b/pkg/resources/resources_support.go
index b16595889..2dc27637b 100644
--- a/pkg/resources/resources_support.go
+++ b/pkg/resources/resources_support.go
@@ -31,7 +31,11 @@ import (
 	"github.com/apache/camel-k/v2/pkg/util"
 )
 
+//
 // ResourceAsString returns the named resource content as string.
+// Warning : do not remove the go:generate line as it is used to update the resources file in case of CRD changes.
+//
+//go:generate go run ../../cmd/util/vfs-gen resources config
 func ResourceAsString(name string) (string, error) {
 	data, err := Resource(name)
 	return string(data), err