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

Rename `GroupHierarchy` to `GroupDescendant`

parent 1e4e51816043
......@@ -118,7 +118,7 @@ def destroy
protected
def setup_children(parent)
@children = GroupChildrenFinder.new(current_user: current_user,
@children = GroupDescendantsFinder.new(current_user: current_user,
parent_group: parent,
params: params).execute
@children = @children.page(params[:page])
......
class GroupChildrenFinder
class GroupDescendantsFinder
include Gitlab::Allowable
attr_reader :current_user, :parent_group, :params
......@@ -38,31 +38,33 @@ def project_count
private
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
def direct_subgroups
def direct_child_groups
GroupsFinder.new(current_user,
parent: parent_group,
all_available: true).execute
end
def all_subgroups
def all_descendant_groups
Gitlab::GroupHierarchy.new(Group.where(id: parent_group)).base_and_descendants
end
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
def subgroups
return Group.none unless Group.supports_nested_groups?
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]
subgroups_matching_filter
else
direct_subgroups
direct_child_groups
end
groups.sort(params[:sort])
end
......@@ -74,7 +76,7 @@ def direct_child_projects
def projects_matching_filter
ProjectsFinder.new(current_user: current_user).execute
.search(params[:filter])
.where(namespace: all_subgroups)
.where(namespace: all_descendant_groups)
end
def projects
......
module GroupHierarchy
module GroupDescendant
def hierarchy(hierarchy_base = nil)
tree_for_child(self, self, hierarchy_base)
expand_hierarchy_for_child(self, self, hierarchy_base)
end
def parent
......@@ -11,29 +11,29 @@ def parent
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?
raise ArgumentError.new('specified base is not part of the tree')
end
if child.parent && child.parent != hierarchy_base
tree_for_child(child.parent,
{ child.parent => tree },
expand_hierarchy_for_child(child.parent,
{ child.parent => hierarchy },
hierarchy_base)
else
tree
hierarchy
end
end
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
def self.merge_hierarchies(hierarchies, hierarchy_base = nil)
hierarchies = Array.wrap(hierarchies)
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')
end
......@@ -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
#
# Handled cases
# [Hash, GroupHierarchy]
# [Hash, GroupDescendant]
elsif first_child.is_a?(Hash) && first_child.keys.include?(second_child)
first_child
elsif second_child.is_a?(Hash) && second_child.keys.include?(first_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.
#
# Handled cases:
# [GroupHierarchy, Array], [GroupHierarchy, GroupHierarchy], [Array, Array]
# [GroupDescendant, Array], [GroupDescendant, GroupDescendant], [Array, Array]
else
Array.wrap(first_child) + Array.wrap(second_child)
end
......
......@@ -6,7 +6,7 @@ class Group < Namespace
include Avatarable
include Referable
include SelectForProjectAuthorization
include GroupHierarchy
include GroupDescendant
has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent
alias_method :members, :group_members
......
......@@ -17,7 +17,7 @@ class Project < ActiveRecord::Base
include ProjectFeaturesCompatibility
include SelectForProjectAuthorization
include Routable
include GroupHierarchy
include GroupDescendant
extend Gitlab::ConfigHelper
extend Gitlab::CurrentSettings
......@@ -1521,10 +1521,6 @@ def public_path_for_source_path(path, commit_sha)
map.public_path_for_source_path(path)
end
def parent
namespace
end
def parent_changed?
namespace_id_changed?
end
......
......@@ -55,7 +55,7 @@ def permission
unless: lambda { |_instance, _options| project? }
def children_finder
@children_finder ||= GroupChildrenFinder.new(current_user: request.current_user,
@children_finder ||= GroupDescendantsFinder.new(current_user: request.current_user,
parent_group: object)
end
......
......@@ -24,10 +24,10 @@ def represent(resource, opts = {}, entity_class = nil)
protected
def represent_hierarchies(children, opts)
if children.is_a?(GroupHierarchy)
if children.is_a?(GroupDescendant)
represent_hierarchy(children.hierarchy(hierarchy_root), opts).first
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
end
end
......
require 'spec_helper'
describe GroupChildrenFinder do
describe GroupDescendantsFinder do
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:params) { {} }
......
require 'spec_helper'
describe GroupHierarchy, :nested_groups do
describe GroupDescendant, :nested_groups do
let(:parent) { create(:group) }
let(:subgroup) { create(:group, parent: parent) }
let(:subsub_group) { create(:group, parent: subgroup) }
......@@ -141,6 +141,33 @@
expect(described_class.merge_hierarchies([parent, subgroup])).to eq(expected_hierarchy)
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
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