@@ -47,7 +47,12 class IssueRelation < ActiveRecord::Base | |||||
47 | if issue_from && issue_to |
|
47 | if issue_from && issue_to | |
48 | errors.add :issue_to_id, :invalid if issue_from_id == issue_to_id |
|
48 | errors.add :issue_to_id, :invalid if issue_from_id == issue_to_id | |
49 | errors.add :issue_to_id, :not_same_project unless issue_from.project_id == issue_to.project_id || Setting.cross_project_issue_relations? |
|
49 | errors.add :issue_to_id, :not_same_project unless issue_from.project_id == issue_to.project_id || Setting.cross_project_issue_relations? | |
50 | errors.add_to_base :circular_dependency if issue_to.all_dependent_issues.include? issue_from |
|
50 | #detect circular dependencies depending wether the relation should be reversed | |
|
51 | if TYPES.has_key?(relation_type) && TYPES[relation_type][:reverse] | |||
|
52 | errors.add_to_base :circular_dependency if issue_from.all_dependent_issues.include? issue_to | |||
|
53 | else | |||
|
54 | errors.add_to_base :circular_dependency if issue_to.all_dependent_issues.include? issue_from | |||
|
55 | end | |||
51 | errors.add_to_base :cant_link_an_issue_with_a_descendant if issue_from.is_descendant_of?(issue_to) || issue_from.is_ancestor_of?(issue_to) |
|
56 | errors.add_to_base :cant_link_an_issue_with_a_descendant if issue_from.is_descendant_of?(issue_to) || issue_from.is_ancestor_of?(issue_to) | |
52 | end |
|
57 | end | |
53 | end |
|
58 | end |
@@ -74,6 +74,8 class IssueRelationsControllerTest < ActionController::TestCase | |||||
74 | :relation => {:issue_to_id => '4', :relation_type => 'relates', :delay => ''} |
|
74 | :relation => {:issue_to_id => '4', :relation_type => 'relates', :delay => ''} | |
75 | end |
|
75 | end | |
76 | end |
|
76 | end | |
|
77 | ||||
|
78 | should "prevent relation creation when there's a circular dependency" | |||
77 |
|
79 | |||
78 | def test_destroy |
|
80 | def test_destroy | |
79 | assert_difference 'IssueRelation.count', -1 do |
|
81 | assert_difference 'IssueRelation.count', -1 do |
@@ -44,6 +44,9 class IssueRelationTest < ActiveSupport::TestCase | |||||
44 | assert_equal from, relation.issue_to |
|
44 | assert_equal from, relation.issue_to | |
45 | end |
|
45 | end | |
46 |
|
46 | |||
|
47 | # TODO : document why it shouldn't be reversed if validation fails : having | |||
|
48 | # relations reversed before the validation would allow simpler code for the | |||
|
49 | # validation | |||
47 | def test_follows_relation_should_not_be_reversed_if_validation_fails |
|
50 | def test_follows_relation_should_not_be_reversed_if_validation_fails | |
48 | from = Issue.find(1) |
|
51 | from = Issue.find(1) | |
49 | to = Issue.find(2) |
|
52 | to = Issue.find(2) | |
@@ -82,4 +85,13 class IssueRelationTest < ActiveSupport::TestCase | |||||
82 | assert !r.save |
|
85 | assert !r.save | |
83 | assert_not_nil r.errors.on(:base) |
|
86 | assert_not_nil r.errors.on(:base) | |
84 | end |
|
87 | end | |
|
88 | ||||
|
89 | def test_validates_circular_dependency_on_reverse_relations | |||
|
90 | IssueRelation.delete_all | |||
|
91 | assert IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(3), :relation_type => IssueRelation::TYPE_BLOCKS) | |||
|
92 | assert IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => IssueRelation::TYPE_BLOCKED) | |||
|
93 | r = IssueRelation.new(:issue_from => Issue.find(2), :issue_to => Issue.find(1), :relation_type => IssueRelation::TYPE_BLOCKED) | |||
|
94 | assert !r.save | |||
|
95 | assert_not_nil r.errors.on(:base) | |||
|
96 | end | |||
85 | end |
|
97 | end |
General Comments 0
You need to be logged in to leave comments.
Login now