diff --git a/resources/repo.rb b/resources/repo.rb index 858303c..86ec05c 100644 --- a/resources/repo.rb +++ b/resources/repo.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'shellwords' + provides :packagecloud_repo unified_mode true default_action :add @@ -259,20 +261,21 @@ def install_gem repo_url = read_token(repo_url).to_s execute "install packagecloud #{new_resource.name} repo as gem source" do - command "gem source --add #{repo_url}" - not_if "gem source --list | grep #{repo_url}" + command Shellwords.join(['gem', 'source', '--add', repo_url]) + not_if { gem_source_exists?(repo_url) } end end def remove_gem repo_url = construct_uri_with_options(base_url: new_resource.base_url, repo: new_resource.repository).to_s - repo_uri = URI(repo_url) - escaped_repo_path = Regexp.escape(repo_uri.path) - escaped_repo_host = Regexp.escape(repo_uri.host) - execute "remove packagecloud #{new_resource.name} repo as gem source" do - command "gem sources --list | ruby -ne 'puts $_ if $_ =~ %r{#{escaped_repo_host}.*#{escaped_repo_path}}' | xargs -r -n1 gem sources --remove" - only_if "gem sources --list | ruby -ne 'exit 0 if $_ =~ %r{#{escaped_repo_host}.*#{escaped_repo_path}}; END { exit 1 }'" + ruby_block "remove packagecloud #{new_resource.name} repo as gem source" do + block do + gem_sources_matching(repo_url).each do |source| + shell_out!(Shellwords.join(['gem', 'sources', '--remove', source])) + end + end + only_if { gem_source_exists?(repo_url) } end end @@ -296,6 +299,27 @@ def read_token(repo_url) repo_url end + def gem_sources + cmd = shell_out('gem sources --list') + return [] unless cmd.exitstatus == 0 + + cmd.stdout.lines.map(&:strip) + end + + def gem_sources_matching(repo_url) + repo_uri = URI(repo_url) + gem_sources.select do |source| + source_uri = URI(source) + source_uri.host == repo_uri.host && source_uri.path.start_with?(repo_uri.path) + rescue URI::InvalidURIError + false + end + end + + def gem_source_exists?(repo_url) + gem_sources_matching(repo_url).any? + end + def install_endpoint_params dist = dist_name diff --git a/spec/unit/resources/repo_spec.rb b/spec/unit/resources/repo_spec.rb index f9ffff0..9d2ef58 100644 --- a/spec/unit/resources/repo_spec.rb +++ b/spec/unit/resources/repo_spec.rb @@ -90,12 +90,11 @@ context 'with gem source' do platform 'ubuntu', '24.04' - before do - stub_command('gem source --list | grep https://packagecloud.io/test/repo/').and_return(false) - stub_command("gem sources --list | ruby -ne 'exit 0 if $_ =~ %r{packagecloud\\.io.*/test/repo/}; END { exit 1 }'").and_return(true) - end - context 'with action :add' do + stubs_for_provider('packagecloud_repo[test/repo]') do |provider| + allow(provider).to receive_shell_out('gem sources --list', stdout: '') + end + recipe do packagecloud_repo 'test/repo' do type 'gem' @@ -106,6 +105,10 @@ end context 'with action :remove' do + stubs_for_provider('packagecloud_repo[test/repo]') do |provider| + allow(provider).to receive_shell_out('gem sources --list', stdout: "https://packagecloud.io/test/repo/\n") + end + recipe do packagecloud_repo 'test/repo' do type 'gem' @@ -113,7 +116,7 @@ end end - it { is_expected.to run_execute('remove packagecloud test/repo repo as gem source') } + it { is_expected.to run_ruby_block('remove packagecloud test/repo repo as gem source') } end end end