diff --git a/lib/rmt/mirror.rb b/lib/rmt/mirror.rb index 747d93f9e..a78f94dc7 100644 --- a/lib/rmt/mirror.rb +++ b/lib/rmt/mirror.rb @@ -13,5 +13,18 @@ def initialize(repository:, base_dir:, logger:, mirror_sources: false, is_airgap end def detect_repository_type + search = { + repomd: File.join(repository.external_url, RPM_FILE_NEEDLE), + debian: File.join(repository.external_url, DEB_FILE_NEEDLE) + } + + search.each do |key, url| + request = RMT::HttpRequest.new(url, method: :head, followlocation: true) + request.on_success do + return key + end + request.run + end + nil end end diff --git a/lib/rmt/mirror/repomd.rb b/lib/rmt/mirror/repomd.rb index 31ed454bd..05b586b84 100644 --- a/lib/rmt/mirror/repomd.rb +++ b/lib/rmt/mirror/repomd.rb @@ -10,7 +10,7 @@ class RMT::Mirror::Repomd::Exception < RuntimeError include RMT::Deduplicator include RMT::FileValidator - def initialize(mirroring_base_dir: RMT::DEFAULT_MIRROR_DIR, logger:, mirror_src: false, airgap_mode: false) + def initialize(logger:, mirroring_base_dir: RMT::DEFAULT_MIRROR_DIR, mirror_src: false, airgap_mode: false) @mirroring_base_dir = mirroring_base_dir @logger = logger @mirror_src = mirror_src @@ -153,8 +153,8 @@ def mirror_packages(metadata_files, repository_dir, repository_url) package_file_references = package_references.map do |reference| RMT::Mirror::FileReference.build_from_metadata(reference, - base_dir: repository_dir, - base_url: repository_url) + base_dir: repository_dir, + base_url: repository_url) end failed_downloads = download_package_files(package_file_references) diff --git a/spec/lib/rmt/mirror/repomd_spec.rb b/spec/lib/rmt/mirror/repomd_spec.rb index 8f676f9fd..d574716f6 100644 --- a/spec/lib/rmt/mirror/repomd_spec.rb +++ b/spec/lib/rmt/mirror/repomd_spec.rb @@ -200,7 +200,7 @@ before do expect(logger).to receive(:info).with(/Mirroring repository/).once expect(logger).to receive(:info).with('Repository metadata signatures are missing').once - expect(logger).to receive(:info).with(/↓/).at_least(1).times + expect(logger).to receive(:info).with(/↓/).at_least(:once) rmt_mirror.mirror(**mirror_params) end @@ -234,7 +234,7 @@ before do expect(logger).to receive(:info).with(/Mirroring repository/).once - expect(logger).to receive(:info).with(/↓/).at_least(1).times + expect(logger).to receive(:info).with(/↓/).at_least(:once) rmt_mirror.mirror(**mirror_params) end @@ -289,6 +289,7 @@ context "when can't create tmp dir", vcr: { cassette_name: 'mirroring_product' } do before { allow(Dir).to receive(:mktmpdir).and_raise('mktmpdir exception') } + it 'handles the exception' do expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception) end @@ -302,6 +303,7 @@ .with([file_reference_containing_path('repodata/repomd.xml')]) .and_raise(RMT::Downloader::Exception, "418 - I'm a teapot") end + it 'handles RMT::Downloader::Exception' do expect { rmt_mirror.mirror(**mirror_params) } .to raise_error(RMT::Mirror::Repomd::Exception, "Error while mirroring metadata: 418 - I'm a teapot") @@ -343,10 +345,12 @@ context "when can't download some of the license files" do before do allow_any_instance_of(RMT::Downloader).to receive(:download_multi).and_wrap_original do |klass, *args| - raise RMT::Downloader::Exception.new('') if args[0][0].local_path =~ /license/ + raise RMT::Downloader::Exception.new('') if /license/.match?(args[0][0].local_path) + klass.call(*args) end end + it 'handles RMT::Downloader::Exception', vcr: { cassette_name: 'mirroring_product' } do expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception, /Error while mirroring license files:/) end @@ -354,6 +358,7 @@ context "when can't parse metadata", vcr: { cassette_name: 'mirroring_product' } do before { allow_any_instance_of(RepomdParser::RepomdXmlParser).to receive(:parse).and_raise('Parse error') } + it 'removes the temporary metadata directory' do expect { rmt_mirror.mirror(**mirror_params) } .to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring metadata: Parse error') @@ -365,6 +370,7 @@ context 'when Interrupt is raised', vcr: { cassette_name: 'mirroring_product' } do before { allow_any_instance_of(RepomdParser::RepomdXmlParser).to receive(:parse).and_raise(Interrupt.new) } + it 'removes the temporary metadata directory' do expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(Interrupt) @@ -377,21 +383,27 @@ it 'handles RMT::Downloader::Exception' do allow_any_instance_of(RMT::Downloader).to receive(:make_request).and_wrap_original do |klass, *args| # raise the exception only for the RPMs/DRPMs - raise(RMT::Downloader::Exception, "418 - I'm a teapot") if args[0].local_path =~ /rpm$/ + raise(RMT::Downloader::Exception, "418 - I'm a teapot") if /rpm$/.match?(args[0].local_path) + klass.call(*args) end - expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files') + expect do + rmt_mirror.mirror(**mirror_params) + end.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files') end it 'handles RMT::ChecksumVerifier::Exception' do allow_any_instance_of(RMT::Downloader).to receive(:make_request).and_wrap_original do |klass, *args| # raise the exception only for the RPMs/DRPMs - raise(RMT::ChecksumVerifier::Exception, "Checksum doesn't match") if args[0].local_path =~ /rpm$/ + raise(RMT::ChecksumVerifier::Exception, "Checksum doesn't match") if /rpm$/.match?(args[0].local_path) + klass.call(*args) end - expect { rmt_mirror.mirror(**mirror_params) }.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files') + expect do + rmt_mirror.mirror(**mirror_params) + end.to raise_error(RMT::Mirror::Repomd::Exception, 'Error while mirroring packages: Failed to download 6 files') end end end @@ -795,7 +807,7 @@ it 'mirrors as normal' do expect(logger).to receive(:info).with(/Mirroring repository/).once expect(logger).to receive(:info).with('Repository metadata signatures are missing').once - expect(logger).to receive(:info).with(/↓/).at_least(1).times + expect(logger).to receive(:info).with(/↓/).at_least(:once) allow_any_instance_of(RMT::Downloader).to receive(:finalize_download).and_wrap_original do |klass, *args| if args[1].local_path.include?('repodata/repomd.xml.key') @@ -817,7 +829,7 @@ it 'raises RMT::Mirror::Repomd::Exception' do expect(logger).to receive(:info).with(/Mirroring repository/).once - expect(logger).to receive(:info).with(/↓/).at_least(1).times + expect(logger).to receive(:info).with(/↓/).at_least(:once) expect_any_instance_of(described_class).to( receive(:mirror_metadata).and_call_original @@ -833,7 +845,7 @@ expect { rmt_mirror.mirror(**mirror_params) }.to raise_error( RMT::Mirror::Repomd::Exception, - 'Error while mirroring metadata: Downloading repo signature/key failed with: HTTP request failed, HTTP code 502' + 'Error while mirroring metadata: Downloading repo signature/key failed with: HTTP request failed, HTTP code 502' ) end end diff --git a/spec/lib/rmt/mirror_spec.rb b/spec/lib/rmt/mirror_spec.rb index edf9302d1..e7de0d856 100644 --- a/spec/lib/rmt/mirror_spec.rb +++ b/spec/lib/rmt/mirror_spec.rb @@ -14,24 +14,33 @@ end describe '#detect_repository_type' do + let(:repomd_url) { 'http://some.test.us/path/directory/repodata/repomd.xml' } + let(:debian_url) { 'http://some.test.us/path/directory/Release' } + context 'repomd repository' do it 'detects a repomd repository' do + stub_request(:head, repomd_url).to_return(status: 200, body: '', headers: {}) + expect(mirror.detect_repository_type).to eq(:repomd) end end context 'debian flat repository' do it 'detects a flat debian repository' do + stub_request(:head, repomd_url).to_return(status: 404, body: '', headers: {}) + stub_request(:head, debian_url).to_return(status: 200, body: '', headers: {}) + expect(mirror.detect_repository_type).to eq(:debian) end end - context 'debian repository' do - it 'detects a full blown debian repository and raises' - end - context 'unknown repository type' do - it 'raises if a unknown repository type is detected' + it 'raises if a unknown repository type is detected' do + stub_request(:head, repomd_url).to_return(status: 404, body: '', headers: {}) + stub_request(:head, debian_url).to_return(status: 404, body: '', headers: {}) + + expect(mirror.detect_repository_type).to be_nil + end end end end