lib/rb_sys/cargo/metadata.rb
# frozen_string_literal: true require "open3" require "psych" module RbSys module Cargo # Extracts metadata from a Cargo project using `cargo metadata`. class Metadata attr_reader :name def initialize(name) raise ArgumentError, "name must be a String" unless name.is_a?(String) @name = name end # @api private def self.delegates_to_cargo_metadata(*methods) methods.each do |method| define_method(method) { cargo_metadata.fetch(method.to_s) } end end # @api private def self.delegates_to_package_metadata(*methods) methods.each do |method| define_method(method) { package_metadata.fetch(method.to_s) } end end delegates_to_cargo_metadata :target_directory, :workspace_root, :packages delegates_to_package_metadata :manifest_path, :version, :id, :edition, :targets, :features, :metadata # Returns the path where the Cargo project's Cargo.toml is located. # # @return [String] def manifest_directory @manifest_directory ||= File.dirname(manifest_path) end private def package_metadata return @package_metadata if @package_metadata found = cargo_metadata.fetch("packages").find { |p| p.fetch("name") == name } raise PackageNotFoundError, @name unless found @package_metadata = found end def cargo_metadata return @cargo_metadata if @cargo_metadata ::Gem.load_yaml cargo = ENV["CARGO"] || "cargo" args = ["metadata", "--no-deps", "--format-version", "1"] out, stderr, _status = Open3.capture3(cargo, *args) @cargo_metadata = Gem::SafeYAML.safe_load(out) rescue => err raise CargoMetadataError.new(err, stderr, manifest_path) end end end end