Commit 9b260b67 authored by Alex Kalderimis's avatar Alex Kalderimis

Further simplification of parsing

This moves all error handling to a single call to `valid?`, eliminating
the need to store the input string on the identifier, and allowing
removal of several methods. In return, all other methods are made
nil-safe.
parent 4eb9765e
...@@ -3,10 +3,12 @@ ...@@ -3,10 +3,12 @@
module Gitlab module Gitlab
class GlRepository class GlRepository
class Identifier class Identifier
IllegalIdentifier = Class.new(ArgumentError) include Gitlab::Utils::StrongMemoize
def self.parse(gl_repository_str) InvalidIdentifier = Class.new(ArgumentError)
segments = gl_repository_str&.split('-')
def self.parse(gl_repository)
segments = gl_repository&.split('-')
# gl_repository can either have 2 or 3 segments: # gl_repository can either have 2 or 3 segments:
# "wiki-1" is the older 2-segment format, where container is implied. # "wiki-1" is the older 2-segment format, where container is implied.
...@@ -14,68 +16,70 @@ module Gitlab ...@@ -14,68 +16,70 @@ module Gitlab
# #
# TODO: convert all 2-segment format to 3-segment: # TODO: convert all 2-segment format to 3-segment:
# https://gitlab.com/gitlab-org/gitlab/-/issues/219192 # https://gitlab.com/gitlab-org/gitlab/-/issues/219192
case segments&.size identifier = case segments&.size
when 2 when 2
TwoPartIdentifier.new(gl_repository_str, *segments) TwoPartIdentifier.new(*segments)
when 3 when 3
ThreePartIdentifier.new(gl_repository_str, *segments) ThreePartIdentifier.new(*segments)
else end
raise IllegalIdentifier, %Q(Invalid GL Repository "#{gl_repository_str}")
end return identifier if identifier&.valid?
raise InvalidIdentifier, %Q(Invalid GL Repository "#{gl_repository}")
end end
class TwoPartIdentifier < Identifier class TwoPartIdentifier < Identifier
def initialize(gl_repository_str, repo_type_name, container_id_str) def initialize(repo_type_name, container_id_str)
@gl_repository_str = gl_repository_str
@repo_type_name = repo_type_name
@container_id_str = container_id_str @container_id_str = container_id_str
@repo_type_name = repo_type_name
end end
private
def container_class def container_class
repo_type.container_class repo_type&.container_class
end end
end end
class ThreePartIdentifier < Identifier class ThreePartIdentifier < Identifier
attr_reader :container_type def initialize(container_type, container_id_str, repo_type_name)
def initialize(gl_repository_str, container_type, container_id_str, repo_type_name)
@gl_repository_str = gl_repository_str
@container_type = container_type
@container_id_str = container_id_str @container_id_str = container_id_str
@container_type = container_type
@repo_type_name = repo_type_name @repo_type_name = repo_type_name
end end
private
def container_class def container_class
case container_type case @container_type
when 'project' when 'project'
Project Project
when 'group' when 'group'
Group Group
else
raise_error
end end
end end
end end
def repo_type
strong_memoize(:repo_type) {Gitlab::GlRepository.types[repo_type_name] }
end
def container def container
@container ||= container_class.find_by_id(container_id) strong_memoize(:container) do
container_class&.find_by_id(container_id) if container_id
end
end end
def repo_type def valid?
@repo_type ||= (Gitlab::GlRepository.types[repo_type_name] || raise_error) repo_type.present? && container_class.present? && container_id&.positive?
end end
private private
attr_reader :gl_repository_str, :container_id_str, :repo_type_name attr_reader :container_id_str, :repo_type_name
def container_id def container_id
Integer(container_id_str, 10, exception: false) || raise_error strong_memoize(:container_id) { Integer(container_id_str, 10, exception: false) }
end
def raise_error
raise IllegalIdentifier, %Q(Invalid GL Repository "#{gl_repository_str}")
end end
end end
end end
......
...@@ -14,6 +14,19 @@ describe Gitlab::GlRepository::Identifier do ...@@ -14,6 +14,19 @@ describe Gitlab::GlRepository::Identifier do
let(:expected_container) { project } let(:expected_container) { project }
let(:expected_type) { Gitlab::GlRepository::PROJECT } let(:expected_type) { Gitlab::GlRepository::PROJECT }
end end
it_behaves_like 'parsing gl_repository identifier' do
let(:record_id) { project.id }
let(:identifier) { "project-#{record_id}-project" }
let(:expected_container) { project }
let(:expected_type) { Gitlab::GlRepository::PROJECT }
end
it_behaves_like 'parsing gl_repository identifier' do
let(:identifier) { "project-1000000" }
let(:expected_container) { nil }
let(:expected_type) { Gitlab::GlRepository::PROJECT }
end
end end
describe 'wiki' do describe 'wiki' do
...@@ -23,6 +36,13 @@ describe Gitlab::GlRepository::Identifier do ...@@ -23,6 +36,13 @@ describe Gitlab::GlRepository::Identifier do
let(:expected_container) { project } let(:expected_container) { project }
let(:expected_type) { Gitlab::GlRepository::WIKI } let(:expected_type) { Gitlab::GlRepository::WIKI }
end end
it_behaves_like 'parsing gl_repository identifier' do
let(:record_id) { project.id }
let(:identifier) { "project-#{record_id}-wiki" }
let(:expected_container) { project }
let(:expected_type) { Gitlab::GlRepository::WIKI }
end
end end
describe 'snippet' do describe 'snippet' do
...@@ -59,7 +79,11 @@ describe Gitlab::GlRepository::Identifier do ...@@ -59,7 +79,11 @@ describe Gitlab::GlRepository::Identifier do
[ [
'wiki-noid', 'wiki-noid',
'foo-2', 'foo-2',
'project-0',
'2-project',
'snippet-2-wiki', 'snippet-2-wiki',
'project-wibble-wiki',
'wiki-1-project',
'snippet', 'snippet',
'project-1-wiki-bar' 'project-1-wiki-bar'
] ]
......
...@@ -12,14 +12,7 @@ RSpec.shared_examples 'parsing gl_repository identifier' do ...@@ -12,14 +12,7 @@ RSpec.shared_examples 'parsing gl_repository identifier' do
end end
RSpec.shared_examples 'illegal gl_identifier' do RSpec.shared_examples 'illegal gl_identifier' do
subject do
described_class.parse(identifier).tap do |ident|
ident.repo_type
ident.container
end
end
it 'raises an error' do it 'raises an error' do
expect { subject }.to raise_error(described_class::IllegalIdentifier) expect { described_class.parse(identifier) }.to raise_error(described_class::InvalidIdentifier)
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment