diff options
Diffstat (limited to 'lib/container_registry/path.rb')
-rw-r--r-- | lib/container_registry/path.rb | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/container_registry/path.rb b/lib/container_registry/path.rb new file mode 100644 index 00000000000..61849a40383 --- /dev/null +++ b/lib/container_registry/path.rb @@ -0,0 +1,76 @@ +module ContainerRegistry + ## + # Class responsible for extracting project and repository name from + # image repository path provided by a containers registry API response. + # + # Example: + # + # some/group/my_project/my/image -> + # project: some/group/my_project + # repository: my/image + # + class Path + InvalidRegistryPathError = Class.new(StandardError) + + LEVELS_SUPPORTED = 3 + + def initialize(path) + @path = path.to_s.downcase + end + + def valid? + @path =~ Gitlab::Regex.container_repository_name_regex && + components.size > 1 && + components.size < Namespace::NUMBER_OF_ANCESTORS_ALLOWED + end + + def components + @components ||= @path.split('/') + end + + def nodes + raise InvalidRegistryPathError unless valid? + + @nodes ||= components.size.downto(2).map do |length| + components.take(length).join('/') + end + end + + def has_project? + repository_project.present? + end + + def has_repository? + return false unless has_project? + + repository_project.container_repositories + .where(name: repository_name).any? + end + + def root_repository? + @path == project_path + end + + def repository_project + @project ||= Project + .where_full_path_in(nodes.first(LEVELS_SUPPORTED)) + .first + end + + def repository_name + return unless has_project? + + @path.remove(%r(^#{Regexp.escape(project_path)}/?)) + end + + def project_path + return unless has_project? + + repository_project.full_path.downcase + end + + def to_s + @path + end + end +end |