github.com/oam-dev/kubevela@v1.9.11/pkg/utils/file.go (about) 1 /* 2 Copyright 2022 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package utils 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 "io/fs" 24 "net/url" 25 "os" 26 "path/filepath" 27 "strings" 28 29 "github.com/pkg/errors" 30 31 "github.com/oam-dev/kubevela/pkg/utils/common" 32 ) 33 34 // FileData data of a file at the path 35 type FileData struct { 36 Path string 37 Data []byte 38 } 39 40 // LoadDataFromPath load FileData from path 41 // If path is an url, fetch the data from the url 42 // If path is a file, fetch the data from the file 43 // If path is a dir, fetch the data from all the files inside the dir that passes the pathFilter 44 func LoadDataFromPath(ctx context.Context, path string, pathFilter func(string) bool) ([]FileData, error) { 45 if path == "-" { 46 bs, err := io.ReadAll(os.Stdin) 47 if err != nil { 48 return nil, fmt.Errorf("failed to get data from stdin: %w", err) 49 } 50 return []FileData{{Path: path, Data: bs}}, nil 51 } 52 53 if IsValidURL(path) { 54 bs, err := common.HTTPGetWithOption(ctx, path, nil) 55 if err != nil { 56 return nil, fmt.Errorf("failed to get data from %s: %w", path, err) 57 } 58 return []FileData{{Path: path, Data: bs}}, nil 59 } 60 fileInfo, err := os.Stat(path) 61 if err != nil { 62 return nil, fmt.Errorf("failed to get file info for %s: %w", path, err) 63 } 64 if fileInfo.IsDir() { 65 var data []FileData 66 err = filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { 67 if pathFilter == nil || pathFilter(path) { 68 bs, e := os.ReadFile(filepath.Clean(path)) 69 if e != nil { 70 return e 71 } 72 data = append(data, FileData{Path: path, Data: bs}) 73 } 74 return nil 75 }) 76 if err != nil { 77 return nil, fmt.Errorf("failed to traverse directory %s: %w", path, err) 78 } 79 return data, nil 80 } 81 bs, e := os.ReadFile(filepath.Clean(path)) 82 if e != nil { 83 return nil, fmt.Errorf("failed to read file %s: %w", path, err) 84 } 85 return []FileData{{Path: path, Data: bs}}, nil 86 } 87 88 // IsJSONYAMLorCUEFile check if the path is a json or yaml file 89 func IsJSONYAMLorCUEFile(path string) bool { 90 return strings.HasSuffix(path, ".json") || 91 strings.HasSuffix(path, ".yaml") || 92 strings.HasSuffix(path, ".yml") || 93 strings.HasSuffix(path, ".cue") 94 } 95 96 // IsCUEFile check if the path is a cue file 97 func IsCUEFile(path string) bool { 98 return strings.HasSuffix(path, ".cue") 99 } 100 101 // IsEmptyDir checks if a given path is an empty directory 102 func IsEmptyDir(path string) (bool, error) { 103 f, err := os.Open(filepath.Clean(path)) 104 if err != nil { 105 return false, err 106 } 107 defer func(f *os.File) { 108 _ = f.Close() 109 }(f) 110 111 // Read just one file in the dir (just read names, which is faster) 112 _, err = f.Readdirnames(1) 113 // If the error is EOF, the dir is empty 114 if errors.Is(err, io.EOF) { 115 return true, nil 116 } 117 118 return false, err 119 } 120 121 // GetFilenameFromLocalOrRemote returns the filename of a local path or a URL. 122 // It doesn't guarantee that the file or URL actually exists. 123 func GetFilenameFromLocalOrRemote(path string) (string, error) { 124 if !IsValidURL(path) { 125 abs, err := filepath.Abs(path) 126 if err != nil { 127 return "", err 128 } 129 return strings.TrimSuffix(filepath.Base(abs), filepath.Ext(abs)), nil 130 } 131 132 u, err := url.Parse(path) 133 if err != nil { 134 return "", err 135 } 136 137 return strings.TrimSuffix(filepath.Base(u.Path), filepath.Ext(u.Path)), nil 138 }