From 5664dafd1dcb63655903d1fb9d7974dfb3bbfc16 Mon Sep 17 00:00:00 2001 From: Ian Ker-Seymer Date: Thu, 18 Apr 2024 17:39:43 -0400 Subject: [PATCH] More robustly detect cargo metadata --- gem/exe/rb-sys-dock | 10 ++++- gem/lib/rb_sys/cargo/metadata.rb | 30 ++++++++++++++ gem/lib/rb_sys/extensiontask.rb | 2 +- gem/test/test_cargo_metadata.rb | 67 ++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/gem/exe/rb-sys-dock b/gem/exe/rb-sys-dock index a8bd1a41..f6877b31 100755 --- a/gem/exe/rb-sys-dock +++ b/gem/exe/rb-sys-dock @@ -18,7 +18,13 @@ OPTIONS = { } def cargo_metadata - @cargo_metadata ||= RbSys::Cargo::Metadata.new("rb-sys-dock", deps: true) + return @cargo_metadata if defined?(@cargo_metadata) + + @cargo_metadata = begin + RbSys::Cargo::Metadata.inferred(deps: true) + rescue + nil + end end def logger @@ -421,7 +427,7 @@ def set_env end def lint_rb_sys - cargo_version = cargo_metadata.rb_sys_version + cargo_version = cargo_metadata&.rb_sys_version || RbSys::VERSION return if cargo_version == RbSys::VERSION logger.warn("Cargo rb-sys version (#{cargo_version}) does not match Ruby gem version (#{RbSys::VERSION})") rescue => e diff --git a/gem/lib/rb_sys/cargo/metadata.rb b/gem/lib/rb_sys/cargo/metadata.rb index b039c49b..79d5bda7 100644 --- a/gem/lib/rb_sys/cargo/metadata.rb +++ b/gem/lib/rb_sys/cargo/metadata.rb @@ -9,6 +9,26 @@ module Cargo class Metadata attr_reader :name + class << self + # Infers the Cargo project's name from the Cargo.toml file. + # + # @return [RbSys::Cargo::Metadata] + def inferred(deps: false) + new(File.read("Cargo.toml").match(/^name = "(.*)"/)[1], deps: deps) + rescue + new(File.basename(Dir.pwd), deps: deps) + end + + # Initializes a new Cargo::Metadata instance or infers the Cargo project's name. + # + # @param name [String] the name of the Cargo project + def new_or_inferred(name, deps: false) + new(name, deps: deps).load! + rescue CargoMetadataError + inferred + end + end + # Initializes a new Cargo::Metadata instance. # # @param name [String] the name of the Cargo project @@ -92,12 +112,22 @@ def metadata end # Returns the rb-sys version, if any. + # + # @return [String] def rb_sys_version pkg = packages.find { |p| p.fetch("name") == "rb-sys" } return unless pkg pkg["version"] end + # Eagerly run `cargo metadata`, raising a RbSys::CargoCargoMetadataError` if it fails. + # + # @return [RbSys::Cargo::Metadata] + def load! + cargo_metadata + self + end + private def package_metadata diff --git a/gem/lib/rb_sys/extensiontask.rb b/gem/lib/rb_sys/extensiontask.rb index 42c476ca..6f310d66 100644 --- a/gem/lib/rb_sys/extensiontask.rb +++ b/gem/lib/rb_sys/extensiontask.rb @@ -57,7 +57,7 @@ def define end def cargo_metadata - @cargo_metadata ||= Cargo::Metadata.new(@name) + @cargo_metadata ||= Cargo::Metadata.new_or_inferred(@name) end def extconf diff --git a/gem/test/test_cargo_metadata.rb b/gem/test/test_cargo_metadata.rb index f77f0f38..9021eaa5 100644 --- a/gem/test/test_cargo_metadata.rb +++ b/gem/test/test_cargo_metadata.rb @@ -30,6 +30,73 @@ def test_fails_when_cargo_metadata_fails end end + def test_load_raises_error_when_cargo_metadata_fails + skip if win_target? + + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + assert_raises(RbSys::CargoMetadataError) do + metadata = RbSys::Cargo::Metadata.new("foo") + metadata.load! + end + end + end + end + + def test_load_returns_self + skip if win_target? + + in_new_crate("foo") do |dir| + metadata = RbSys::Cargo::Metadata.new("foo") + + assert_equal metadata, metadata.load! + end + end + + def test_inferred_returns_valid_info + skip if win_target? + + in_new_crate("fooyoo") do |dir| + metadata = RbSys::Cargo::Metadata.inferred + + assert_equal "fooyoo", metadata.name + end + end + + def test_inferred_falls_back_to_dir_name + skip if win_target? + + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + metadata = RbSys::Cargo::Metadata.inferred + + assert_equal File.basename(dir), metadata.name + end + end + end + + def test_new_or_inferred_returns_valid_info + skip if win_target? + + in_new_crate("foo") do |dir| + metadata = RbSys::Cargo::Metadata.new_or_inferred("foofer") + + assert_equal "foofer", metadata.name + end + end + + def test_new_or_inferred_falls_back_to_inferred + skip if win_target? + + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + metadata = RbSys::Cargo::Metadata.new_or_inferred("foofer") + + assert_equal File.basename(dir), metadata.name + end + end + end + private def in_new_crate(name, &blk)