github.com/psrajat/prototool@v1.3.0/internal/protoc/protoc.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 protoc 22 23 import ( 24 "github.com/golang/protobuf/protoc-gen-go/descriptor" 25 "github.com/uber/prototool/internal/file" 26 "github.com/uber/prototool/internal/settings" 27 "github.com/uber/prototool/internal/text" 28 "go.uber.org/zap" 29 ) 30 31 // Downloader downloads and caches protobuf. 32 type Downloader interface { 33 // Download protobuf. 34 // 35 // If already downloaded, this has no effect. This is thread-safe. 36 // This will download to ${XDG_CACHE_HOME}/prototool/$(uname -s)/$(uname -m) 37 // unless overridden by a DownloaderOption. 38 // If ${XDG_CACHE_HOME} is not set, it defaults to ${HOME}/Library/Caches on 39 // Darwin, and ${HOME}/.cache on Linux. 40 // If ${HOME} is not set, an error will be returned. 41 // 42 // Returns the path to the downloaded protobuf artifacts. 43 // 44 // ProtocPath and WellKnownTypesIncludePath implicitly call this. 45 Download() (string, error) 46 47 // Get the path to protoc. 48 // 49 // If not downloaded, this downloads and caches protobuf. This is thread-safe. 50 ProtocPath() (string, error) 51 52 // Get the path to include for the well-known types. 53 // 54 // Inside this directory will be the subdirectories google/protobuf. 55 // 56 // If not downloaded, this downloads and caches protobuf. This is thread-safe. 57 WellKnownTypesIncludePath() (string, error) 58 59 // Delete any downloaded artifacts. 60 // 61 // This is not thread-safe and no calls to other functions can be reliably 62 // made simultaneously. 63 Delete() error 64 } 65 66 // DownloaderOption is an option for a new Downloader. 67 type DownloaderOption func(*downloader) 68 69 // DownloaderWithLogger returns a DownloaderOption that uses the given logger. 70 // 71 // The default is to use zap.NewNop(). 72 func DownloaderWithLogger(logger *zap.Logger) DownloaderOption { 73 return func(downloader *downloader) { 74 downloader.logger = logger 75 } 76 } 77 78 // DownloaderWithCachePath returns a DownloaderOption that uses the given cachePath. 79 // 80 // The default is ${XDG_CACHE_HOME}/prototool/$(uname -s)/$(uname -m). 81 func DownloaderWithCachePath(cachePath string) DownloaderOption { 82 return func(downloader *downloader) { 83 downloader.cachePath = cachePath 84 } 85 } 86 87 // DownloaderWithProtocBinPath returns a DownloaderOption that uses the given protoc binary path. 88 func DownloaderWithProtocBinPath(protocBinPath string) DownloaderOption { 89 return func(downloader *downloader) { 90 downloader.protocBinPath = protocBinPath 91 } 92 } 93 94 // DownloaderWithProtocWKTPath returns a DownloaderOption that uses the given path to include 95 // the well-known types. 96 func DownloaderWithProtocWKTPath(protocWKTPath string) DownloaderOption { 97 return func(downloader *downloader) { 98 downloader.protocWKTPath = protocWKTPath 99 } 100 } 101 102 // DownloaderWithProtocURL returns a DownloaderOption that uses the given protoc zip file URL. 103 // 104 // The default is https://github.com/protocolbuffers/protobuf/releases/download/vVERSION/protoc-VERSION-OS-ARCH.zip. 105 func DownloaderWithProtocURL(protocURL string) DownloaderOption { 106 return func(downloader *downloader) { 107 downloader.protocURL = protocURL 108 } 109 } 110 111 // NewDownloader returns a new Downloader for the given config and DownloaderOptions. 112 func NewDownloader(config settings.Config, options ...DownloaderOption) (Downloader, error) { 113 return newDownloader(config, options...) 114 } 115 116 // CompileResult is the result of a compile 117 type CompileResult struct { 118 // The failures from all calls. 119 Failures []*text.Failure 120 // Will not be set if there are any failures. 121 // 122 // Will only be set if the CompilerWithFileDescriptorSet 123 // option is used. 124 FileDescriptorSets []*descriptor.FileDescriptorSet 125 } 126 127 // Compiler compiles protobuf files. 128 type Compiler interface { 129 // Compile the protobuf files with protoc. 130 // 131 // If there are compile failures, they will be returned in the slice 132 // and there will be no error. The caller can determine if this is 133 // an error case. If there is any other type of error, or some output 134 // from protoc cannot be interpreted, an error will be returned. 135 Compile(*file.ProtoSet) (*CompileResult, error) 136 137 // Return the protoc commands that would be run on Compile. 138 // 139 // This will ignore the CompilerWithFileDescriptorSet option. 140 ProtocCommands(*file.ProtoSet) ([]string, error) 141 } 142 143 // CompilerOption is an option for a new Compiler. 144 type CompilerOption func(*compiler) 145 146 // CompilerWithLogger returns a CompilerOption that uses the given logger. 147 // 148 // The default is to use zap.NewNop(). 149 func CompilerWithLogger(logger *zap.Logger) CompilerOption { 150 return func(compiler *compiler) { 151 compiler.logger = logger 152 } 153 } 154 155 // CompilerWithCachePath returns a CompilerOption that uses the given cachePath. 156 // 157 // The default is ${XDG_CACHE_HOME}/prototool/$(uname -s)/$(uname -m). 158 func CompilerWithCachePath(cachePath string) CompilerOption { 159 return func(compiler *compiler) { 160 compiler.cachePath = cachePath 161 } 162 } 163 164 // CompilerWithProtocBinPath returns a CompilerOption that uses the given protoc binary path. 165 // 166 func CompilerWithProtocBinPath(protocBinPath string) CompilerOption { 167 return func(compiler *compiler) { 168 compiler.protocBinPath = protocBinPath 169 } 170 } 171 172 // CompilerWithProtocWKTPath returns a CompilerOption that uses the given path to include the 173 // well-known types. 174 func CompilerWithProtocWKTPath(protocWKTPath string) CompilerOption { 175 return func(compiler *compiler) { 176 compiler.protocWKTPath = protocWKTPath 177 } 178 } 179 180 // CompilerWithProtocURL returns a CompilerOption that uses the given protoc zip file URL. 181 // 182 // The default is https://github.com/protocolbuffers/protobuf/releases/download/vVERSION/protoc-VERSION-OS-ARCH.zip. 183 func CompilerWithProtocURL(protocURL string) CompilerOption { 184 return func(compiler *compiler) { 185 compiler.protocURL = protocURL 186 } 187 } 188 189 // CompilerWithGen says to also generate the code. 190 func CompilerWithGen() CompilerOption { 191 return func(compiler *compiler) { 192 compiler.doGen = true 193 } 194 } 195 196 // CompilerWithFileDescriptorSet says to also return the FileDescriptorSet. 197 func CompilerWithFileDescriptorSet() CompilerOption { 198 return func(compiler *compiler) { 199 compiler.doFileDescriptorSet = true 200 } 201 } 202 203 // NewCompiler returns a new Compiler. 204 func NewCompiler(options ...CompilerOption) Compiler { 205 return newCompiler(options...) 206 }