Copy relations between subtasks when copying an issue with its subtasks When an issue is copied together with its subtasks, relations between the copied subtasks (precedes/follows, blocks/blocked, relates, etc.) are lost: Issue#after_create_from_copy only copies the subtasks themselves, not the relations among them. This patch keeps a mapping from the original child issues to their copies and, after all subtasks have been created, replicates every relation whose both ends were copied. Relations pointing to issues outside the copied subtree are intentionally left out. Generated against the 6.1-stable branch (6.1.4). Apply from the Redmine root directory with: patch -p1 < issue_copy_subtask_relations-6.1-stable.patch Related: #17068 diff --git a/app/models/issue.rb b/app/models/issue.rb index 3772f60..00547fd 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1777,12 +1777,12 @@ class Issue < ApplicationRecord unless @copied_from.leaf? || @copy_options[:subtasks] == false copy_options = (@copy_options || {}).merge(:subtasks => false) - copied_issue_ids = {@copied_from.id => self.id} + copied_issues = {@copied_from.id => self} @copied_from.reload.descendants.reorder("#{Issue.table_name}.lft").each do |child| # Do not copy self when copying an issue as a descendant of the copied issue next if child == self # Do not copy subtasks of issues that were not copied - next unless copied_issue_ids[child.parent_id] + next unless copied_issues[child.parent_id] # Do not copy subtasks that are not visible to avoid potential disclosure of private data unless child.visible? @@ -1800,7 +1800,7 @@ class Issue < ApplicationRecord end copy.author = author copy.project = project - copy.parent_issue_id = copied_issue_ids[child.parent_id] + copy.parent_issue_id = copied_issues[child.parent_id].id unless child.fixed_version.present? && child.fixed_version.status == 'open' copy.fixed_version_id = nil end @@ -1818,7 +1818,22 @@ class Issue < ApplicationRecord end next end - copied_issue_ids[child.id] = copy.id + copied_issues[child.id] = copy + end + + # Replicate dependencies between copied children + @copied_from.reload.descendants.reorder("#{Issue.table_name}.lft").each do |child| + copy = copied_issues[child.id] + next unless copy + child.relations_to.each do |rel| + next unless copied_issues.key?(rel.issue_from.id) + from = Issue.find_by_id(copied_issues[rel.issue_from.id].id) + next unless from + relation = IssueRelation.new(:issue_from => from, :issue_to => copy, :relation_type => rel.relation_type) + unless relation.save + logger.error "Could not create relation while copying ##{child.id} to ##{copy.id} due to validation errors: #{relation.errors.full_messages.join(', ')}" if logger + end + end end end @after_create_from_copy_handled = true