github.com/Zenithar/prototool@v1.3.0/internal/file/file.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package file 22 23 import ( 24 "fmt" 25 "path/filepath" 26 "time" 27 28 "github.com/uber/prototool/internal/settings" 29 "go.uber.org/zap" 30 ) 31 32 // DefaultWalkTimeout is the default walk timeout. 33 const DefaultWalkTimeout time.Duration = 3 * time.Second 34 35 // ProtoSet represents a set of .proto files and an associated config. 36 // 37 // ProtoSets will be validated if returned from this package. 38 type ProtoSet struct { 39 // The working directory path. 40 // Must be absolute. 41 // Must be cleaned. 42 WorkDirPath string 43 // The given directory path. 44 // This will be the same as WorkDirPath if files were given. 45 // Must be absolute. 46 // Must be cleaned. 47 DirPath string 48 // The directory path to slice of .proto files. 49 // All paths must be absolute. 50 // Must be cleaned. 51 DirPathToFiles map[string][]*ProtoFile 52 // The associated Config. 53 // Must be valid. 54 // The DirPath on the config may differ from the DirPath 55 // on the ProtoSet. 56 Config settings.Config 57 } 58 59 // ProtoFile represents a .proto file. 60 type ProtoFile struct { 61 // The path to the .proto file. 62 // Must be absolute. 63 // Must be cleaned. 64 Path string 65 // The path to display in output. 66 // This will be relative to the working directory, or the absolute path 67 // if the file was outside the working directory. 68 DisplayPath string 69 } 70 71 // ProtoSetProvider provides ProtoSets. 72 type ProtoSetProvider interface { 73 // GetMultipleForDir gets the ProtoSets for the given dirPath. 74 // Each ProtoSet will have the config assocated with all files associated with 75 // the ProtoSet. 76 // 77 // This will return all .proto files in the directory of the associated config file 78 // and all it's subdirectories, or the given directory and its subdirectories 79 // if there is no config file. 80 // 81 // Configs will be searched for starting at the directory of each .proto file 82 // and going up a directory until hitting root. 83 GetMultipleForDir(workDirPath string, dirPath string) ([]*ProtoSet, error) 84 85 // GetMultipleForFiles gets the ProtoSets for the given filePaths. 86 // Each ProtoSet will have the config assocated with all files associated with 87 // the ProtoSet. 88 // 89 // Configs will be searched for starting at the directory of each .proto file 90 // and going up a directory until hitting root. 91 // 92 // This ignores excludes, all files given will be included. 93 GetMultipleForFiles(workDirPath string, filePaths ...string) ([]*ProtoSet, error) 94 95 // GetForDir does the same logic as GetMultipleForDir, but returns an error if there 96 // is not exactly one ProtoSet. We keep the original logic and testing for multiple 97 // ProtoSets around as we are still discussing this pre-v1.0. 98 // https://github.com/uber/prototool/issues/10 99 // https://github.com/uber/prototool/issues/93 100 GetForDir(workDirPath string, dirPath string) (*ProtoSet, error) 101 102 // GetForFiles does the same logic as GetMultipleForFiles, but returns an error if there 103 // is not exactly one ProtoSet. We keep the original logic and testing for multiple 104 // ProtoSets around as we are still discussing this pre-v1.0. 105 // https://github.com/uber/prototool/issues/10 106 // https://github.com/uber/prototool/issues/93 107 GetForFiles(workDirPath string, filePaths ...string) (*ProtoSet, error) 108 } 109 110 // ProtoSetProviderOption is an option for a new ProtoSetProvider. 111 type ProtoSetProviderOption func(*protoSetProvider) 112 113 // ProtoSetProviderWithLogger returns a ProtoSetProviderOption that uses the given logger. 114 // 115 // The default is to use zap.NewNop(). 116 func ProtoSetProviderWithLogger(logger *zap.Logger) ProtoSetProviderOption { 117 return func(protoSetProvider *protoSetProvider) { 118 protoSetProvider.logger = logger 119 } 120 } 121 122 // ProtoSetProviderWithConfigData returns a ProtoSetProviderOption that uses the given configuration 123 // data instead of using configuration files that are found. This acts as if there is only one 124 // configuration file at the current working directory. All found configuration files are ignored. 125 func ProtoSetProviderWithConfigData(configData string) ProtoSetProviderOption { 126 return func(protoSetProvider *protoSetProvider) { 127 protoSetProvider.configData = configData 128 } 129 } 130 131 // ProtoSetProviderWithWalkTimeout returns a ProtoSetProviderOption will timeout after walking 132 // a directory structure when searching for Protobuf files after the given amount of time. 133 // 134 // The default is to timeout after DefaultTimeoutDuration. 135 // Set to 0 for no timeout. 136 func ProtoSetProviderWithWalkTimeout(walkTimeout time.Duration) ProtoSetProviderOption { 137 return func(protoSetProvider *protoSetProvider) { 138 protoSetProvider.walkTimeout = walkTimeout 139 } 140 } 141 142 // NewProtoSetProvider returns a new ProtoSetProvider. 143 func NewProtoSetProvider(options ...ProtoSetProviderOption) ProtoSetProvider { 144 return newProtoSetProvider(options...) 145 } 146 147 // AbsClean returns the cleaned absolute path of the given path. 148 func AbsClean(path string) (string, error) { 149 if path == "" { 150 return path, nil 151 } 152 if !filepath.IsAbs(path) { 153 return filepath.Abs(path) 154 } 155 return filepath.Clean(path), nil 156 } 157 158 // CheckAbs is a convenience functions for determining 159 // whether a path is an absolute path. 160 func CheckAbs(path string) error { 161 if !filepath.IsAbs(path) { 162 return fmt.Errorf("expected absolute path but was %s", path) 163 } 164 return nil 165 }