Commit 22aa0344 authored by Bob Van Landuyt's avatar Bob Van Landuyt
Browse files

Rename `GroupHierarchy` to `GroupDescendant`

parent 1e4e51816043
...@@ -118,9 +118,9 @@ def destroy ...@@ -118,9 +118,9 @@ def destroy
protected protected
def setup_children(parent) def setup_children(parent)
@children = GroupChildrenFinder.new(current_user: current_user, @children = GroupDescendantsFinder.new(current_user: current_user,
parent_group: parent, parent_group: parent,
params: params).execute params: params).execute
@children = @children.page(params[:page]) @children = @children.page(params[:page])
end end
......
class GroupChildrenFinder class GroupDescendantsFinder
include Gitlab::Allowable include Gitlab::Allowable
attr_reader :current_user, :parent_group, :params attr_reader :current_user, :parent_group, :params
...@@ -38,31 +38,33 @@ def project_count ...@@ -38,31 +38,33 @@ def project_count
private private
def children def children
@children ||= subgroups.with_route.includes(:route, :parent) + projects.with_route.includes(:route, :namespace) @children ||= subgroups.with_route.includes(:parent) + projects.with_route.includes(:namespace)
end end
def direct_subgroups def direct_child_groups
GroupsFinder.new(current_user, GroupsFinder.new(current_user,
parent: parent_group, parent: parent_group,
all_available: true).execute all_available: true).execute
end end
def all_subgroups def all_descendant_groups
Gitlab::GroupHierarchy.new(Group.where(id: parent_group)).base_and_descendants Gitlab::GroupHierarchy.new(Group.where(id: parent_group)).base_and_descendants
end end
def subgroups_matching_filter def subgroups_matching_filter
all_subgroups.where.not(id: parent_group).search(params[:filter]) all_descendant_groups.where.not(id: parent_group).search(params[:filter])
end end
def subgroups def subgroups
return Group.none unless Group.supports_nested_groups? return Group.none unless Group.supports_nested_groups?
return Group.none unless can?(current_user, :read_group, parent_group) return Group.none unless can?(current_user, :read_group, parent_group)
# When filtering subgroups, we want to find all matches withing the tree of
# descendants to show to the user
groups = if params[:filter] groups = if params[:filter]
subgroups_matching_filter subgroups_matching_filter
else else
direct_subgroups direct_child_groups
end end
groups.sort(params[:sort]) groups.sort(params[:sort])
end end
...@@ -74,7 +76,7 @@ def direct_child_projects ...@@ -74,7 +76,7 @@ def direct_child_projects
def projects_matching_filter def projects_matching_filter
ProjectsFinder.new(current_user: current_user).execute ProjectsFinder.new(current_user: current_user).execute
.search(params[:filter]) .search(params[:filter])
.where(namespace: all_subgroups) .where(namespace: all_descendant_groups)
end end
def projects def projects
......
module GroupHierarchy module GroupDescendant
def hierarchy(hierarchy_base = nil) def hierarchy(hierarchy_base = nil)
tree_for_child(self, self, hierarchy_base) expand_hierarchy_for_child(self, self, hierarchy_base)
end end
def parent def parent
...@@ -11,29 +11,29 @@ def parent ...@@ -11,29 +11,29 @@ def parent
end end
end end
def tree_for_child(child, tree, hierarchy_base) def expand_hierarchy_for_child(child, hierarchy, hierarchy_base)
if child.parent.nil? && hierarchy_base.present? if child.parent.nil? && hierarchy_base.present?
raise ArgumentError.new('specified base is not part of the tree') raise ArgumentError.new('specified base is not part of the tree')
end end
if child.parent && child.parent != hierarchy_base if child.parent && child.parent != hierarchy_base
tree_for_child(child.parent, expand_hierarchy_for_child(child.parent,
{ child.parent => tree }, { child.parent => hierarchy },
hierarchy_base) hierarchy_base)
else else
tree hierarchy
end end
end end
def merge_hierarchy(other_element, hierarchy_base = nil) def merge_hierarchy(other_element, hierarchy_base = nil)
GroupHierarchy.merge_hierarchies([self, other_element], hierarchy_base) GroupDescendant.merge_hierarchies([self, other_element], hierarchy_base)
end end
def self.merge_hierarchies(hierarchies, hierarchy_base = nil) def self.merge_hierarchies(hierarchies, hierarchy_base = nil)
hierarchies = Array.wrap(hierarchies) hierarchies = Array.wrap(hierarchies)
return if hierarchies.empty? return if hierarchies.empty?
unless hierarchies.all? { |hierarchy| hierarchy.is_a?(GroupHierarchy) } unless hierarchies.all? { |hierarchy| hierarchy.is_a?(GroupDescendant) }
raise ArgumentError.new('element is not a hierarchy') raise ArgumentError.new('element is not a hierarchy')
end end
...@@ -68,16 +68,16 @@ def self.merge_values(first_child, second_child) ...@@ -68,16 +68,16 @@ def self.merge_values(first_child, second_child)
# we can check if its already in the hash. If so, we don't need to do anything # we can check if its already in the hash. If so, we don't need to do anything
# #
# Handled cases # Handled cases
# [Hash, GroupHierarchy] # [Hash, GroupDescendant]
elsif first_child.is_a?(Hash) && first_child.keys.include?(second_child) elsif first_child.is_a?(Hash) && first_child.keys.include?(second_child)
first_child first_child
elsif second_child.is_a?(Hash) && second_child.keys.include?(first_child) elsif second_child.is_a?(Hash) && second_child.keys.include?(first_child)
second_child second_child
# If one or both elements are a GroupHierarchy, we wrap create an array # If one or both elements are a GroupDescendant, we wrap create an array
# combining them. # combining them.
# #
# Handled cases: # Handled cases:
# [GroupHierarchy, Array], [GroupHierarchy, GroupHierarchy], [Array, Array] # [GroupDescendant, Array], [GroupDescendant, GroupDescendant], [Array, Array]
else else
Array.wrap(first_child) + Array.wrap(second_child) Array.wrap(first_child) + Array.wrap(second_child)
end end
......
...@@ -6,7 +6,7 @@ class Group < Namespace ...@@ -6,7 +6,7 @@ class Group < Namespace
include Avatarable include Avatarable
include Referable include Referable
include SelectForProjectAuthorization include SelectForProjectAuthorization
include GroupHierarchy include GroupDescendant
has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent
alias_method :members, :group_members alias_method :members, :group_members
......
...@@ -17,7 +17,7 @@ class Project < ActiveRecord::Base ...@@ -17,7 +17,7 @@ class Project < ActiveRecord::Base
include ProjectFeaturesCompatibility include ProjectFeaturesCompatibility
include SelectForProjectAuthorization include SelectForProjectAuthorization
include Routable include Routable
include GroupHierarchy include GroupDescendant
extend Gitlab::ConfigHelper extend Gitlab::ConfigHelper
extend Gitlab::CurrentSettings extend Gitlab::CurrentSettings
...@@ -1521,10 +1521,6 @@ def public_path_for_source_path(path, commit_sha) ...@@ -1521,10 +1521,6 @@ def public_path_for_source_path(path, commit_sha)
map.public_path_for_source_path(path) map.public_path_for_source_path(path)
end end
def parent
namespace
end
def parent_changed? def parent_changed?
namespace_id_changed? namespace_id_changed?
end end
......
...@@ -55,8 +55,8 @@ def permission ...@@ -55,8 +55,8 @@ def permission
unless: lambda { |_instance, _options| project? } unless: lambda { |_instance, _options| project? }
def children_finder def children_finder
@children_finder ||= GroupChildrenFinder.new(current_user: request.current_user, @children_finder ||= GroupDescendantsFinder.new(current_user: request.current_user,
parent_group: object) parent_group: object)
end end
def children_count def children_count
......
...@@ -24,10 +24,10 @@ def represent(resource, opts = {}, entity_class = nil) ...@@ -24,10 +24,10 @@ def represent(resource, opts = {}, entity_class = nil)
protected protected
def represent_hierarchies(children, opts) def represent_hierarchies(children, opts)
if children.is_a?(GroupHierarchy) if children.is_a?(GroupDescendant)
represent_hierarchy(children.hierarchy(hierarchy_root), opts).first represent_hierarchy(children.hierarchy(hierarchy_root), opts).first
else else
hierarchies = Array.wrap(GroupHierarchy.merge_hierarchies(children, hierarchy_root)) hierarchies = Array.wrap(GroupDescendant.merge_hierarchies(children, hierarchy_root))
hierarchies.map { |hierarchy| represent_hierarchy(hierarchy, opts) }.flatten hierarchies.map { |hierarchy| represent_hierarchy(hierarchy, opts) }.flatten
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe GroupChildrenFinder do describe GroupDescendantsFinder do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:group) { create(:group) } let(:group) { create(:group) }
let(:params) { {} } let(:params) { {} }
......
require 'spec_helper' require 'spec_helper'
describe GroupHierarchy, :nested_groups do describe GroupDescendant, :nested_groups do
let(:parent) { create(:group) } let(:parent) { create(:group) }
let(:subgroup) { create(:group, parent: parent) } let(:subgroup) { create(:group, parent: parent) }
let(:subsub_group) { create(:group, parent: subgroup) } let(:subsub_group) { create(:group, parent: subgroup) }
...@@ -141,6 +141,33 @@ ...@@ -141,6 +141,33 @@
expect(described_class.merge_hierarchies([parent, subgroup])).to eq(expected_hierarchy) expect(described_class.merge_hierarchies([parent, subgroup])).to eq(expected_hierarchy)
end end
it 'merges complex hierarchies' do
project = create(:project, namespace: parent)
sub_project = create(:project, namespace: subgroup)
subsubsub_group = create(:group, parent: subsub_group)
subsub_project = create(:project, namespace: subsub_group)
subsubsub_project = create(:project, namespace: subsubsub_group)
other_subgroup = create(:group, parent: parent)
other_subproject = create(:project, namespace: other_subgroup)
projects = [project, subsubsub_project, sub_project, other_subproject, subsub_project]
expected_hierarchy = [
project,
{
subgroup => [
{ subsub_group => [{ subsubsub_group => subsubsub_project }, subsub_project] },
sub_project
]
},
{ other_subgroup => other_subproject }
]
actual_hierarchy = described_class.merge_hierarchies(projects, parent)
expect(actual_hierarchy).to eq(expected_hierarchy)
end
end end
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