# frozen_string_literal: true module Gitlab class GlRepository class Identifier include Gitlab::Utils::StrongMemoize InvalidIdentifier = Class.new(ArgumentError) def self.parse(gl_repository) segments = gl_repository&.split('-') # gl_repository can either have 2 or 3 segments: # # TODO: convert all 2-segment format to 3-segment: # https://gitlab.com/gitlab-org/gitlab/-/issues/219192 identifier = case segments&.size when 2 TwoPartIdentifier.new(*segments) when 3 ThreePartIdentifier.new(*segments) end return identifier if identifier&.valid? raise InvalidIdentifier, %Q(Invalid GL Repository "#{gl_repository}") end # The older 2-segment format, where the container is implied. # eg. project-1, wiki-1 class TwoPartIdentifier < Identifier def initialize(repo_type_name, container_id_str) @container_id_str = container_id_str @repo_type_name = repo_type_name end private def container_class repo_type.container_class end end # The newer 3-segment format, where the container is explicit # eg. group-1-wiki, project-1-wiki class ThreePartIdentifier < Identifier def initialize(container_type, container_id_str, repo_type_name) @container_id_str = container_id_str @container_type = container_type @repo_type_name = repo_type_name end private def container_class case @container_type when 'project' Project when 'group' Group end end end def repo_type strong_memoize(:repo_type) { Gitlab::GlRepository.types[repo_type_name] } end def container strong_memoize(:container) { container_class.find_by_id(container_id) } end def valid? repo_type.present? && container_class.present? && container_id&.positive? end private attr_reader :container_id_str, :repo_type_name def container_id strong_memoize(:container_id) { Integer(container_id_str, 10, exception: false) } end end end end