Index: app/helpers/changeset_relations_helper.rb
===================================================================
--- app/helpers/changeset_relations_helper.rb	(revision 0)
+++ app/helpers/changeset_relations_helper.rb	(revision 0)
@@ -0,0 +1,2 @@
+module ChangesetRelationsHelper
+end
Index: app/controllers/changeset_relations_controller.rb
===================================================================
--- app/controllers/changeset_relations_controller.rb	(revision 0)
+++ app/controllers/changeset_relations_controller.rb	(revision 0)
@@ -0,0 +1,55 @@
+class ChangesetRelationsController < ApplicationController
+  
+  
+  before_filter  :find_project, :authorize
+  
+  def new
+    @changeset = Changeset.find(:first, :conditions => {:revision => params[:changeset][:revision], :repository_id => @project.repository})
+    if @changeset.nil?
+      @changeset = Changeset.new(:revision => params[:changeset][:revision])
+      @changeset.errors.add('revision_not_found_error', '')
+    else
+      @changeset.issues << @issue
+      @changeset.save if request.post?
+    end
+    @issue.reload
+    respond_to do |format|
+      format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
+      format.js do
+        render :update do |page|
+          page.replace_html "issue-changesets-list", :partial => 'issues/changesets', :locals => { :changesets => @issue.changesets }
+          if @changeset.errors.empty?
+            page << "$('changeset_revision').value = ''"
+          end
+        end
+      end
+    end
+  end
+  
+  def destroy
+    changeset = Changeset.find(params[:id])
+    if request.post? && ! changeset.nil? && changeset.issues.include?(@issue)
+      changeset.issues.delete(@issue)
+      @issue.reload
+    end
+    respond_to do |format|
+      format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
+      format.js do
+        render(:update) do |page|
+          page.replace_html "issue-changesets-list", :partial => 'issues/changesets', :locals => { :changesets => @issue.changesets }
+        end
+      end
+    end
+  end
+  
+  
+  private
+  
+  def find_project
+    @issue = Issue.find(params[:issue_id])
+    @project = @issue.project
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+  
+end
Index: app/views/changeset_relations/_form.html.erb
===================================================================
--- app/views/changeset_relations/_form.html.erb	(revision 0)
+++ app/views/changeset_relations/_form.html.erb	(revision 0)
@@ -0,0 +1,8 @@
+<%= error_messages_for 'changeset' %>
+
+<p><%= l(:label_revision) %> <%= f.text_field :revision, :size => 6 %>
+  <%= submit_tag l(:button_add) %>
+  <%= toggle_link l(:button_cancel), 'new-changeset-form'%>
+</p>
+
+<%= javascript_tag "setPredecessorFieldsVisibility();" %>
Index: app/views/issues/show.rhtml
===================================================================
--- app/views/issues/show.rhtml	(revision 5066)
+++ app/views/issues/show.rhtml	(working copy)
@@ -82,11 +82,18 @@
 
 </div>
 
-<% if @changesets.present? %>
-<div id="issue-changesets">
-<h3><%=l(:label_associated_revisions)%></h3>
-<%= render :partial => 'changesets', :locals => { :changesets => @changesets} %>
-</div>
+<% if !@project.repository.nil? && (@changesets.present? || authorize_for('changeset_relations', 'new')) %>
+  <div id="issue-changesets">
+    <div class="contextual">
+      <% if authorize_for('changeset_relations', 'new') %>
+        <%= toggle_link l(:button_add), 'new-changeset-form'%>
+      <% end %>
+    </div>
+    <h3><%=l(:label_associated_revisions)%></h3>
+    <div id="issue-changesets-list">
+      <%= render :partial => 'changesets', :locals => { :changesets => @changesets } %>
+    </div>
+  </div>
 <% end %>
 
 <% if @journals.present? %>
Index: app/views/issues/_changesets.rhtml
===================================================================
--- app/views/issues/_changesets.rhtml	(revision 5066)
+++ app/views/issues/_changesets.rhtml	(working copy)
@@ -1,10 +1,26 @@
-<% changesets.each do |changeset| %>
+<% remote_form_for(:changeset, @changeset,
+                 :url => {:controller => 'changeset_relations', :action => 'new', :issue_id => @issue},
+                 :method => :post,
+                 :html => {:id => 'new-changeset-form', :style => (@changeset ? '' : 'display: none;')}) do |f| %>
+<%= render :partial => 'changeset_relations/form', :locals => {:f => f}%>
+<% end %>
+<% if !changesets.empty? %>
+  <% changesets.each do |changeset| %>
     <div class="changeset <%= cycle('odd', 'even') %>">
-    <p><%= link_to_revision(changeset, changeset.project,
-                            :text => "#{l(:label_revision)} #{changeset.format_identifier}") %><br />
-        <span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
+    <p><%= link_to("#{l(:label_revision)} #{changeset.revision}",
+                :controller => 'repositories', :action => 'revision', :id => changeset.project, :rev => changeset.revision) %>
+       <span class="contextual">
+       <%= link_to_remote(image_tag('delete.png'), { :url => {:controller => 'changeset_relations', :action => 'destroy', :issue_id => @issue, :id => changeset},
+                                                     :method => :post
+                                                   }, :title => l(:label_changeset_delete)) if authorize_for('changeset_relations', 'destroy') %>
+       </span><br />
+       <span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span>
+    </p>
+
     <div class="changeset-changes">
         <%= textilizable(changeset, :comments) %>
     </div>
     </div>
+  <% end %>
 <% end %>
+
Index: db/migrate/20100531224709_add_manage_changeset_relations_permission.rb
===================================================================
--- db/migrate/20100531224709_add_manage_changeset_relations_permission.rb	(revision 0)
+++ db/migrate/20100531224709_add_manage_changeset_relations_permission.rb	(revision 0)
@@ -0,0 +1,13 @@
+class AddManageChangesetRelationsPermission < ActiveRecord::Migration
+  def self.up
+    Role.find(:all).each do |r|
+      r.add_permission!(:manage_changeset_relations) if r.has_permission?(:manage_issue_relations)
+    end
+  end
+
+  def self.down
+    Role.find(:all).each do |r|
+      r.remove_permission!(:manage_changeset_relations)
+    end
+  end
+end
Index: lib/redmine.rb
===================================================================
--- lib/redmine.rb	(revision 5066)
+++ lib/redmine.rb	(working copy)
@@ -68,6 +68,7 @@
     map.permission :add_issues, {:issues => [:new, :create, :update_form]}
     map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]}
     map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
+    map.permission :manage_changeset_relations, {:changeset_relations => [:new, :destroy]}
     map.permission :manage_subtasks, {}
     map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
     map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
Index: public/stylesheets/application.css
===================================================================
--- public/stylesheets/application.css	(revision 5066)
+++ public/stylesheets/application.css	(working copy)
@@ -289,7 +289,7 @@
 fieldset#filters td.add-filter { text-align: right; vertical-align: top; }
 .buttons { font-size: 0.9em; margin-bottom: 1.4em; margin-top: 1em; }
 
-div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
+div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 0em; background: #fff; padding-left: 1em; font-size: 90%;}
 div#issue-changesets div.changeset { padding: 4px;}
 div#issue-changesets div.changeset { border-bottom: 1px solid #ddd; }
 div#issue-changesets p { margin-top: 0; margin-bottom: 1em;}
Index: config/locales/en.yml
===================================================================
--- config/locales/en.yml	(revision 5066)
+++ config/locales/en.yml	(working copy)
@@ -935,4 +935,6 @@
   enumeration_doc_categories: Document categories
   enumeration_activities: Activities (time tracking)
   enumeration_system_activity: System Activity
-
+  
+  label_changeset_delete: Delete associated revision
+  field_revision_not_found_error: Revision not found in project repository
