Find forks within users/namespaces using fork memberships

This commit is contained in:
Bob Van Landuyt 2017-10-03 17:06:09 +02:00
parent 8160550439
commit f90b27da77
8 changed files with 70 additions and 10 deletions

View file

@ -8,4 +8,8 @@ class ForkNetwork < ActiveRecord::Base
def add_root_as_member def add_root_as_member
projects << root_project projects << root_project
end end
def find_forks_in(other_projects)
projects.where(id: other_projects)
end
end end

View file

@ -139,7 +139,9 @@ class Namespace < ActiveRecord::Base
end end
def find_fork_of(project) def find_fork_of(project)
projects.joins(:forked_project_link).find_by('forked_project_links.forked_from_project_id = ?', project.id) return nil unless project.fork_network
project.fork_network.find_forks_in(projects).first
end end
def lfs_enabled? def lfs_enabled?

View file

@ -1009,6 +1009,11 @@ class Project < ActiveRecord::Base
end end
def forked? def forked?
return true if fork_network && fork_network.root_project != self
# TODO: Use only the above conditional using the `fork_network`
# This is the old conditional that looks at the `forked_project_link`, we
# fall back to this while we're migrating the new models
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
end end

View file

@ -697,15 +697,7 @@ class User < ActiveRecord::Base
end end
def fork_of(project) def fork_of(project)
links = ForkedProjectLink.where( namespace.find_fork_of(project)
forked_from_project_id: project,
forked_to_project_id: personal_projects.unscope(:order)
)
if links.any?
links.first.forked_to_project
else
nil
end
end end
def ldap_user? def ldap_user?

View file

@ -0,0 +1,5 @@
FactoryGirl.define do
factory :fork_network do
association :root_project, factory: :project
end
end

View file

@ -12,6 +12,18 @@ describe ForkNetwork do
end end
end end
describe '#find_fork_in' do
it 'finds all fork of the current network in al collection' do
network = create(:fork_network)
root_project = network.root_project
another_project = fork_project(root_project)
create(:project)
expect(network.find_forks_in(Project.all))
.to contain_exactly(another_project, root_project)
end
end
context 'for a deleted project' do context 'for a deleted project' do
it 'keeps the fork network' do it 'keeps the fork network' do
project = create(:project, :public) project = create(:project, :public)

View file

@ -1,6 +1,8 @@
require 'spec_helper' require 'spec_helper'
describe Namespace do describe Namespace do
include ProjectForksHelper
let!(:namespace) { create(:namespace) } let!(:namespace) { create(:namespace) }
describe 'associations' do describe 'associations' do
@ -520,4 +522,25 @@ describe Namespace do
end end
end end
end end
describe '#has_forks_of?' do
let(:project) { create(:project, :public) }
let!(:forked_project) { fork_project(project, namespace.owner, namespace: namespace) }
before do
# Reset the fork network relation
project.reload
end
it 'knows if there is a direct fork in the namespace' do
expect(namespace.find_fork_of(project)).to eq(forked_project)
end
it 'knows when there is as fork-of-fork in the namespace' do
other_namespace = create(:namespace)
other_fork = fork_project(forked_project, other_namespace.owner, namespace: other_namespace)
expect(other_namespace.find_fork_of(project)).to eq(other_fork)
end
end
end end

View file

@ -1456,6 +1456,23 @@ describe User do
end end
end end
describe '#fork_of' do
let(:user) { create(:user) }
it "returns a user's fork of a project" do
project = create(:project, :public)
user_fork = fork_project(project, user, namespace: user.namespace)
expect(user.fork_of(project)).to eq(user_fork)
end
it 'returns nil if the project does not have a fork network' do
project = create(:project)
expect(user.fork_of(project)).to be_nil
end
end
describe '#can_be_removed?' do describe '#can_be_removed?' do
subject { create(:user) } subject { create(:user) }