require "fileutils" namespace :protobuf do desc "Clean & Compile the protobuf source to ruby classes. Pass PB_NO_CLEAN=1 if you do not want to force-clean first." task :compile, [:package, :source, :destination, :plugin, :file_extension] do |_tasks, args| binpath = ::File.expand_path("../../../../bin", __FILE__) args.with_defaults(:destination => "lib") args.with_defaults(:source => "definitions") args.with_defaults(:plugin => "protoc-gen-ruby-protobuf=#{binpath}/protoc-gen-ruby") args.with_defaults(:file_extension => ".pb.rb") # The local Ruby generator collides with the builtin Ruby generator # # From the protoc docs: # # --plugin=EXECUTABLE # # ...EXECUTABLE may be of the form NAME=PATH, in which case the given plugin name # is mapped to the given executable even if the executable"s own name differs. # # Use the NAME=PATH form to specify an alternative plugin name that avoids the name collision # plugin_name, _plugin_path = args[:plugin].split("=") # The plugin name MUST have the protoc-gen- prefix in order to work, but that prefix is dropped # when using the plugin to generate definitions plugin_name.gsub!("protoc-gen-", "") unless do_not_clean? force_clean! ::Rake::Task[:clean].invoke(args[:package], args[:destination], args[:file_extension]) end command = [] command << "protoc" command << "--plugin=#{args[:plugin]}" command << "--#{plugin_name}_out=#{args[:destination]}" command << "-I #{args[:source]}" command << Dir["#{args[:source]}/#{args[:package]}/**/*.proto"].join(" ") full_command = command.join(" ") puts full_command system(full_command) end desc "Clean the generated *.pb.rb files from the destination package. Pass PB_FORCE_CLEAN=1 to skip confirmation step." task :clean, [:package, :destination, :file_extension] do |_task, args| args.with_defaults(:destination => "lib") args.with_defaults(:file_extension => ".pb.rb") file_extension = args[:file_extension].sub(/\*?\.+/, "") files_to_clean = ::File.join(args[:destination], args[:package], "**", "*.#{file_extension}") if force_clean? || permission_to_clean?(files_to_clean) ::Dir.glob(files_to_clean).each do |file| ::FileUtils.rm(file) end end end def do_not_clean? ! ::ENV.key?("PB_NO_CLEAN") end def force_clean? ::ENV.key?("PB_FORCE_CLEAN") end def force_clean! ::ENV["PB_FORCE_CLEAN"] = "1" end def permission_to_clean?(files_to_clean) puts "Do you really want to remove files matching pattern #{files_to_clean}? (y/n)" ::STDIN.gets.chomp =~ /y(es)?/i end end