From ce795d52adcf670656b661e0899a4b554c01b00a Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Tue, 5 Oct 2021 21:45:24 +0200 Subject: [PATCH] GitService: Improve hostname extraction This commit adds support for more repository notations and provides unit tests. --- lib/modulesync/git_service.rb | 33 ++++++++++++++++--- lib/modulesync/source_code.rb | 10 ++++-- spec/unit/modulesync/git_service_spec.rb | 40 ++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/lib/modulesync/git_service.rb b/lib/modulesync/git_service.rb index e653c7ff..cee3506a 100644 --- a/lib/modulesync/git_service.rb +++ b/lib/modulesync/git_service.rb @@ -89,12 +89,11 @@ def self.endpoint_for(sourcecode:, type:) end # This method attempts to guess the git service endpoint based on remote and type - # FIXME: It only supports "git@hostname:repo_path" scheme def self.guess_endpoint_from(remote:, type:) - pattern = /^git@(.*):(.*)(\.git)*$/ - return nil unless remote.match?(pattern) + hostname = extract_hostname(remote) + return nil if hostname.nil? - endpoint = remote.sub(pattern, 'https://\1') + endpoint = "https://#{hostname}" endpoint += '/api/v4' if type == :gitlab endpoint end @@ -121,5 +120,31 @@ def self.token_for(sourcecode:, type:) token end + + # This method extracts hostname from URL like: + # + # - ssh://[user@]host.xz[:port]/path/to/repo.git/ + # - git://host.xz[:port]/path/to/repo.git/ + # - [user@]host.xz:path/to/repo.git/ + # - http[s]://host.xz[:port]/path/to/repo.git/ + # - ftp[s]://host.xz[:port]/path/to/repo.git/ + # + # Returns nil if + # - /path/to/repo.git/ + # - file:///path/to/repo.git/ + # - any invalid URL + def self.extract_hostname(url) + #pattern = /^((?.*)@)*(?.*):(?[a-zA-Z].*)*$/ + return nil if url.start_with?('/') || url.start_with?('file://') # local path (e.g. file:///path/to/repo) + + unless url.start_with?(/[a-z]+:\/\//) # SSH notation does not contain protocol (e.g. user@server:path/to/repo/) + pattern = /^(.*@)?(?[\w|.]*):(.*)$/ # SSH path (e.g. user@server:repo) + return url.match(pattern)[:hostname] if url.match?(pattern) + end + + return URI.parse(url).host + rescue URI::InvalidURIError => e + return nil + end end end diff --git a/lib/modulesync/source_code.rb b/lib/modulesync/source_code.rb index 10d72633..248bd420 100644 --- a/lib/modulesync/source_code.rb +++ b/lib/modulesync/source_code.rb @@ -48,9 +48,15 @@ def path(*parts) File.join(working_directory, *parts) end + def git_service + @git_service ||= GitService.instantiate(**git_service_configuration) + end + + def git_service_configuration + @git_service_configuration ||= GitService.configuration_for(sourcecode: self) + end + def open_pull_request - git_service_options = GitService.configuration_for(sourcecode: self) - git_service = GitService.instantiate(**git_service_options) git_service.open_pull_request( repo_path: repository_path, namespace: repository_namespace, diff --git a/spec/unit/modulesync/git_service_spec.rb b/spec/unit/modulesync/git_service_spec.rb index d4b115d8..9f372363 100644 --- a/spec/unit/modulesync/git_service_spec.rb +++ b/spec/unit/modulesync/git_service_spec.rb @@ -1,3 +1,4 @@ +require 'modulesync' require 'modulesync/git_service' describe ModuleSync::GitService do @@ -164,4 +165,43 @@ end end end + + RSpec.shared_examples 'hostname_extractor' do |url, hostname| + context "with '#{url}' URL" do + subject { ModuleSync::GitService.extract_hostname(url) } + it "should extract '#{hostname}' as hostname" do + expect(subject).to eq(hostname) + end + end + end + + context '#extract_hostname' do + [ + %w[ssh://user@host.xz:4444/path/to/repo.git/ host.xz], + %w[ssh://user@host.xz:/path/to/repo.git/ host.xz], + %w[ssh://host.xz/path/to/repo.git/ host.xz], + + %w[git://host.xz/path/to/repo.git/ host.xz], + %w[git://host.xz/path/to/repo/ host.xz], + %w[git://host.xz/path/to/repo host.xz], + + %w[user@host.xz:path/to/repo.git/ host.xz], + %w[user@host.xz:path/to/repo.git host.xz], + %w[user@host.xz:path/to/repo host.xz], + %w[host.xz:path/to/repo.git/ host.xz], + + %w[https://host.xz:8443/path/to/repo.git/ host.xz], + %w[https://host.xz/path/to/repo.git/ host.xz], + + %w[ftp://host.xz/path/to/repo/ host.xz], + + ['/path/to/repo.git/', nil], + + ['file:///path/to/repo.git/', nil], + + ['something-invalid', nil], + ].each do |url, hostname| + it_should_behave_like 'hostname_extractor', url, hostname + end + end end