Users with same username or email are automatically mapped. Mapping can be manually adjusted in repository settings. Multiple usernames can be mapped to the same Redmine user. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2006 e93f8b46-1217-0410-a6f0-8f06a7374b81tags/0.8.0-RC1
@@ -44,6 +44,20 @@ class RepositoriesController < ApplicationController | |||
render(:update) {|page| page.replace_html "tab-content-repository", :partial => 'projects/settings/repository'} | |||
end | |||
def committers | |||
@committers = @repository.committers | |||
@users = @project.users | |||
additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id) | |||
@users += User.find_all_by_id(additional_user_ids) unless additional_user_ids.empty? | |||
@users.compact! | |||
@users.sort! | |||
if request.post? | |||
@repository.committer_ids = params[:committers] | |||
flash[:notice] = l(:notice_successful_update) | |||
redirect_to :action => 'committers', :id => @project | |||
end | |||
end | |||
def destroy | |||
@repository.destroy | |||
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository' |
@@ -1,5 +1,5 @@ | |||
# redMine - project management software | |||
# Copyright (C) 2006-2007 Jean-Philippe Lang | |||
# Redmine - project management software | |||
# Copyright (C) 2006-2008 Jean-Philippe Lang | |||
# | |||
# This program is free software; you can redistribute it and/or | |||
# modify it under the terms of the GNU General Public License | |||
@@ -19,13 +19,13 @@ require 'iconv' | |||
class Changeset < ActiveRecord::Base | |||
belongs_to :repository | |||
belongs_to :user | |||
has_many :changes, :dependent => :delete_all | |||
has_and_belongs_to_many :issues | |||
acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.revision}" + (o.comments.blank? ? '' : (': ' + o.comments))}, | |||
:description => :comments, | |||
:datetime => :committed_on, | |||
:author => :committer, | |||
:url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project_id, :rev => o.revision}} | |||
acts_as_searchable :columns => 'comments', | |||
@@ -57,6 +57,14 @@ class Changeset < ActiveRecord::Base | |||
repository.project | |||
end | |||
def author | |||
user || committer.to_s.split('<').first | |||
end | |||
def before_create | |||
self.user = repository.find_committer_user(committer) | |||
end | |||
def after_create | |||
scan_comment_for_issue_ids | |||
end | |||
@@ -96,12 +104,11 @@ class Changeset < ActiveRecord::Base | |||
issue.reload | |||
# don't change the status is the issue is closed | |||
next if issue.status.is_closed? | |||
user = committer_user || User.anonymous | |||
csettext = "r#{self.revision}" | |||
if self.scmid && (! (csettext =~ /^r[0-9]+$/)) | |||
csettext = "commit:\"#{self.scmid}\"" | |||
end | |||
journal = issue.init_journal(user, l(:text_status_changed_by_changeset, csettext)) | |||
journal = issue.init_journal(user || User.anonymous, l(:text_status_changed_by_changeset, csettext)) | |||
issue.status = fix_status | |||
issue.done_ratio = done_ratio if done_ratio | |||
issue.save | |||
@@ -113,16 +120,6 @@ class Changeset < ActiveRecord::Base | |||
self.issues = referenced_issues.uniq | |||
end | |||
# Returns the Redmine User corresponding to the committer | |||
def committer_user | |||
if committer && committer.strip =~ /^([^<]+)(<(.*)>)?$/ | |||
username, email = $1.strip, $3 | |||
u = User.find_by_login(username) | |||
u ||= User.find_by_mail(email) unless email.blank? | |||
u | |||
end | |||
end | |||
# Returns the previous changeset | |||
def previous | |||
@@ -140,7 +137,8 @@ class Changeset < ActiveRecord::Base | |||
end | |||
private | |||
def self.to_utf8(str) | |||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii | |||
encoding = Setting.commit_logs_encoding.to_s.strip |
@@ -96,6 +96,45 @@ class Repository < ActiveRecord::Base | |||
self.changesets.each(&:scan_comment_for_issue_ids) | |||
end | |||
# Returns an array of committers usernames and associated user_id | |||
def committers | |||
@committers ||= Changeset.connection.select_rows("SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}") | |||
end | |||
# Maps committers username to a user ids | |||
def committer_ids=(h) | |||
if h.is_a?(Hash) | |||
committers.each do |committer, user_id| | |||
new_user_id = h[committer] | |||
if new_user_id && (new_user_id.to_i != user_id.to_i) | |||
new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil) | |||
Changeset.update_all("user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }", ["repository_id = ? AND committer = ?", id, committer]) | |||
end | |||
end | |||
@committers = nil | |||
true | |||
else | |||
false | |||
end | |||
end | |||
# Returns the Redmine User corresponding to the given +committer+ | |||
# It will return nil if the committer is not yet mapped and if no User | |||
# with the same username or email was found | |||
def find_committer_user(committer) | |||
if committer | |||
c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user) | |||
if c && c.user | |||
c.user | |||
elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/ | |||
username, email = $1.strip, $3 | |||
u = User.find_by_login(username) | |||
u ||= User.find_by_mail(email) unless email.blank? | |||
u | |||
end | |||
end | |||
end | |||
# fetch new changesets for all repositories | |||
# can be called periodically by an external script | |||
# eg. ruby script/runner "Repository.fetch_changesets" |
@@ -37,6 +37,7 @@ class User < ActiveRecord::Base | |||
has_many :members, :dependent => :delete_all | |||
has_many :projects, :through => :memberships | |||
has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify | |||
has_many :changesets, :dependent => :nullify | |||
has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' | |||
has_one :rss_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'" | |||
belongs_to :auth_source |
@@ -2,7 +2,7 @@ | |||
<div class="changeset <%= cycle('odd', 'even') %>"> | |||
<p><%= link_to("#{l(:label_revision)} #{changeset.revision}", | |||
:controller => 'repositories', :action => 'revision', :id => @project, :rev => changeset.revision) %><br /> | |||
<span class="author"><%= authoring(changeset.committed_on, changeset.committer) %></span></p> | |||
<span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p> | |||
<%= textilizable(changeset, :comments) %> | |||
</div> | |||
<% end %> |
@@ -79,7 +79,7 @@ | |||
pdf.Ln | |||
for changeset in @issue.changesets | |||
pdf.SetFontStyle('B',8) | |||
pdf.Cell(190,5, format_time(changeset.committed_on) + " - " + changeset.committer) | |||
pdf.Cell(190,5, format_time(changeset.committed_on) + " - " + changeset.author) | |||
pdf.Ln | |||
unless changeset.comments.blank? | |||
pdf.SetFontStyle('',8) |
@@ -11,10 +11,13 @@ | |||
</div> | |||
<div class="contextual"> | |||
<% if @repository && !@repository.new_record? %> | |||
<%= link_to(l(:label_user_plural), {:controller => 'repositories', :action => 'committers', :id => @project}, :class => 'icon icon-user') %> | |||
<%= link_to(l(:button_delete), {:controller => 'repositories', :action => 'destroy', :id => @project}, | |||
:confirm => l(:text_are_you_sure), | |||
:method => :post, | |||
:class => 'icon icon-del') if @repository && !@repository.new_record? %> | |||
:class => 'icon icon-del') %> | |||
<% end %> | |||
</div> | |||
<%= submit_tag((@repository.nil? || @repository.new_record?) ? l(:button_create) : l(:button_save), :disabled => @repository.nil?) %> |
@@ -15,10 +15,10 @@ | |||
:class => (entry.is_dir? ? 'icon icon-folder' : 'icon icon-file')%> | |||
</td> | |||
<td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td> | |||
<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %> | |||
<td class="revision"><%= link_to(format_revision(entry.lastrev.name), :action => 'revision', :id => @project, :rev => entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %></td> | |||
<td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td> | |||
<td class="author"><%=h(entry.lastrev.author.to_s.split('<').first) if entry.lastrev %></td> | |||
<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %> | |||
<td class="author"><%= changeset.nil? ? h(entry.lastrev.author.to_s.split('<').first) : changeset.author if entry.lastrev %></td> | |||
<td class="comments"><%=h truncate(changeset.comments, 50) unless changeset.nil? %></td> | |||
</tr> | |||
<% end %> |
@@ -17,7 +17,7 @@ | |||
<td class="checkbox"><%= radio_button_tag('rev', changeset.revision, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < revisions.size) %></td> | |||
<td class="checkbox"><%= radio_button_tag('rev_to', changeset.revision, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('cb-#{line_num}').checked==true) {$('cb-#{line_num-1}').checked=true;}") if show_diff && (line_num > 1) %></td> | |||
<td class="committed_on"><%= format_time(changeset.committed_on) %></td> | |||
<td class="author"><%=h changeset.committer.to_s.split('<').first %></td> | |||
<td class="author"><%=h changeset.author %></td> | |||
<td class="comments"><%= textilizable(truncate_at_line_break(changeset.comments)) %></td> | |||
</tr> | |||
<% line_num += 1 %> |
@@ -0,0 +1,29 @@ | |||
<h2><%= l(:label_repository) %></h2> | |||
<%= simple_format(l(:text_repository_usernames_mapping)) %> | |||
<% if @committers.empty? %> | |||
<p class="nodata"><%= l(:label_no_data) %></p> | |||
<% else %> | |||
<% form_tag({}) do %> | |||
<table class="list"> | |||
<thead> | |||
<tr> | |||
<th><%= l(:field_login) %></th> | |||
<th><%= l(:label_user) %></th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<% @committers.each do |committer, user_id| -%> | |||
<tr class="<%= cycle 'odd', 'even' %>"> | |||
<td><%=h committer %></td> | |||
<td><%= select_tag "committers[#{committer}]", content_tag('option', "-- #{l :actionview_instancetag_blank_option} --", :value => '') + options_from_collection_for_select(@users, 'id', 'name', user_id.to_i) %></td> | |||
</tr> | |||
<% end -%> | |||
</tbody> | |||
</table> | |||
<p><%= submit_tag(l(:button_update)) %></p> | |||
<% end %> | |||
<% end %> |
@@ -22,7 +22,7 @@ | |||
<h2><%= l(:label_revision) %> <%= format_revision(@changeset.revision) %></h2> | |||
<p><% if @changeset.scmid %>ID: <%= @changeset.scmid %><br /><% end %> | |||
<em><%= @changeset.committer.to_s.split('<').first %>, <%= format_time(@changeset.committed_on) %></em></p> | |||
<span class="author"><%= authoring(@changeset.committed_on, @changeset.author) %></span></p> | |||
<%= textilizable @changeset.comments %> | |||
@@ -0,0 +1,9 @@ | |||
class AddChangesetsUserId < ActiveRecord::Migration | |||
def self.up | |||
add_column :changesets, :user_id, :integer, :default => nil | |||
end | |||
def self.down | |||
remove_column :changesets, :user_id | |||
end | |||
end |
@@ -0,0 +1,18 @@ | |||
class PopulateChangesetsUserId < ActiveRecord::Migration | |||
def self.up | |||
committers = Changeset.connection.select_values("SELECT DISTINCT committer FROM #{Changeset.table_name}") | |||
committers.each do |committer| | |||
next if committer.blank? | |||
if committer.strip =~ /^([^<]+)(<(.*)>)?$/ | |||
username, email = $1.strip, $3 | |||
u = User.find_by_login(username) | |||
u ||= User.find_by_mail(email) unless email.blank? | |||
Changeset.update_all("user_id = #{u.id}", ["committer = ?", committer]) unless u.nil? | |||
end | |||
end | |||
end | |||
def self.down | |||
Changeset.update_all('user_id = NULL') | |||
end | |||
end |
@@ -689,3 +689,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -694,3 +694,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -665,6 +665,7 @@ text_user_wrote: '%s wrote:' | |||
text_enumeration_destroy_question: '%d objects are assigned to this value.' | |||
text_enumeration_category_reassign_to: 'Reassign them to this value:' | |||
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." | |||
default_role_manager: Manager | |||
default_role_developper: Developer |
@@ -692,3 +692,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -689,3 +689,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -665,6 +665,7 @@ text_user_wrote: '%s a écrit:' | |||
text_enumeration_destroy_question: 'Cette valeur est affectée à %d objets.' | |||
text_enumeration_category_reassign_to: 'Réaffecter les objets à cette valeur:' | |||
text_email_delivery_not_configured: "L'envoi de mail n'est pas configuré, les notifications sont désactivées.\nConfigurez votre serveur SMTP dans config/email.yml et redémarrez l'application pour les activer." | |||
text_repository_usernames_mapping: "Vous pouvez sélectionner ou modifier l'utilisateur Redmine associé à chaque nom d'utilisateur figurant dans l'historique du dépôt.\nLes utilisateurs avec le même identifiant ou la même adresse mail seront automatiquement associés." | |||
default_role_manager: Manager | |||
default_role_developper: Développeur |
@@ -689,3 +689,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Időnaplók szerkesztése | |||
permission_edit_own_issue_notes: Saját jegyzetek szerkesztése | |||
setting_gravatar_enabled: Felhasználói fényképek engedélyezése | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -689,3 +689,4 @@ permission_edit_time_entries: Modifica time logs | |||
permission_edit_own_issue_notes: Modifica proprie note | |||
setting_gravatar_enabled: Usa icone utente Gravatar | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -689,3 +689,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -691,3 +691,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -691,3 +691,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -724,3 +724,4 @@ permission_edit_own_issue_notes: Edycja własnych notatek | |||
setting_gravatar_enabled: Używaj ikon użytkowników Gravatar | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Editar tempo gasto | |||
permission_edit_own_issue_notes: Editar próprias notas | |||
setting_gravatar_enabled: Usar ícones do Gravatar | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -691,3 +691,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -689,3 +689,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -722,3 +722,4 @@ text_user_mail_option: "Для невыбранных проектов, Вы б | |||
text_user_wrote: '%s написал(а):' | |||
text_wiki_destroy_confirmation: Вы уверены, что хотите удалить данную Wiki и все ее содержимое? | |||
text_workflow_edit: Выберите роль и трекер для редактирования последовательности состояний | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -694,3 +694,4 @@ permission_edit_time_entries: Editácia časových záznamov | |||
permission_edit_own_issue_notes: Editácia vlastných poznámok úlohy | |||
setting_gravatar_enabled: Použitie uživateľských Gravatar ikon | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -692,3 +692,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -691,3 +691,4 @@ permission_edit_time_entries: Edit time logs | |||
permission_edit_own_issue_notes: Edit own notes | |||
setting_gravatar_enabled: Use Gravatar user icons | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -690,3 +690,4 @@ permission_save_queries: Save queries | |||
permission_edit_time_entries: Edit time logs | |||
permission_edit_own_time_entries: Edit own time logs | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -691,3 +691,4 @@ enumeration_issue_priorities: 項目優先權 | |||
enumeration_doc_categories: 文件分類 | |||
enumeration_activities: 活動 (時間追蹤) | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -691,3 +691,4 @@ enumeration_issue_priorities: 问题优先级 | |||
enumeration_doc_categories: 文档类别 | |||
enumeration_activities: 活动(时间跟踪) | |||
label_example: Example | |||
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." |
@@ -88,7 +88,7 @@ Redmine::AccessControl.map do |map| | |||
end | |||
map.project_module :repository do |map| | |||
map.permission :manage_repository, {:repositories => [:edit, :destroy]}, :require => :member | |||
map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member | |||
map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph] | |||
map.permission :view_changesets, :repositories => [:show, :revisions, :revision] | |||
map.permission :commit_access, {} |
@@ -7,6 +7,7 @@ changesets_001: | |||
comments: My very first commit | |||
repository_id: 10 | |||
committer: dlopper | |||
user_id: 3 | |||
changesets_002: | |||
commit_date: 2007-04-12 | |||
committed_on: 2007-04-12 15:14:44 +02:00 | |||
@@ -15,6 +16,7 @@ changesets_002: | |||
comments: 'This commit fixes #1, #2 and references #1 & #3' | |||
repository_id: 10 | |||
committer: dlopper | |||
user_id: 3 | |||
changesets_003: | |||
commit_date: 2007-04-12 | |||
committed_on: 2007-04-12 15:14:44 +02:00 | |||
@@ -25,6 +27,7 @@ changesets_003: | |||
IssueID 666 3 | |||
repository_id: 10 | |||
committer: dlopper | |||
user_id: 3 | |||
changesets_004: | |||
commit_date: 2007-04-12 | |||
committed_on: 2007-04-12 15:14:44 +02:00 | |||
@@ -35,4 +38,5 @@ changesets_004: | |||
IssueID 4 2 | |||
repository_id: 10 | |||
committer: dlopper | |||
user_id: 3 | |||
@@ -43,6 +43,7 @@ roles_001: | |||
- :view_files | |||
- :manage_files | |||
- :browse_repository | |||
- :manage_repository | |||
- :view_changesets | |||
position: 1 |
@@ -61,4 +61,38 @@ class RepositoriesControllerTest < Test::Unit::TestCase | |||
assert_response :success | |||
assert_equal 'image/svg+xml', @response.content_type | |||
end | |||
def test_committers | |||
@request.session[:user_id] = 2 | |||
# add a commit with an unknown user | |||
Changeset.create!(:repository => Project.find(1).repository, :committer => 'foo', :committed_on => Time.now, :revision => 100, :comments => 'Committed by foo.') | |||
get :committers, :id => 1 | |||
assert_response :success | |||
assert_template 'committers' | |||
assert_tag :td, :content => 'dlopper', | |||
:sibling => { :tag => 'td', | |||
:child => { :tag => 'select', :attributes => { :name => 'committers[dlopper]' }, | |||
:child => { :tag => 'option', :content => 'Dave Lopper', | |||
:attributes => { :value => '3', :selected => 'selected' }}}} | |||
assert_tag :td, :content => 'foo', | |||
:sibling => { :tag => 'td', | |||
:child => { :tag => 'select', :attributes => { :name => 'committers[foo]' }}} | |||
assert_no_tag :td, :content => 'foo', | |||
:sibling => { :tag => 'td', | |||
:descendant => { :tag => 'option', :attributes => { :selected => 'selected' }}} | |||
end | |||
def test_map_committers | |||
@request.session[:user_id] = 2 | |||
# add a commit with an unknown user | |||
c = Changeset.create!(:repository => Project.find(1).repository, :committer => 'foo', :committed_on => Time.now, :revision => 100, :comments => 'Committed by foo.') | |||
assert_no_difference "Changeset.count(:conditions => 'user_id = 3')" do | |||
post :committers, :id => 1, :committers => { 'foo' => '2', 'dlopper' => '3'} | |||
assert_redirected_to '/repositories/committers/ecookbook' | |||
assert_equal User.find(2), c.reload.user | |||
end | |||
end | |||
end |
@@ -40,6 +40,7 @@ class RepositoryGitTest < Test::Unit::TestCase | |||
commit = @repository.changesets.find(:first, :order => 'committed_on ASC') | |||
assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments | |||
assert_equal "jsmith <jsmith@foo.bar>", commit.committer | |||
assert_equal User.find_by_login('jsmith'), commit.user | |||
# TODO: add a commit with commit time <> author time to the test repository | |||
assert_equal "2007-12-14 09:22:52".to_time, commit.committed_on | |||
assert_equal "2007-12-14".to_date, commit.commit_date |
@@ -127,4 +127,26 @@ class RepositoryTest < Test::Unit::TestCase | |||
assert_equal ':pserver:login:password@host:/path/to/the/repository', repository.url | |||
assert_equal 'foo', repository.root_url | |||
end | |||
def test_manual_user_mapping | |||
assert_no_difference "Changeset.count(:conditions => 'user_id <> 2')" do | |||
c = Changeset.create!(:repository => @repository, :committer => 'foo', :committed_on => Time.now, :revision => 100, :comments => 'Committed by foo.') | |||
assert_nil c.user | |||
@repository.committer_ids = {'foo' => '2'} | |||
assert_equal User.find(2), c.reload.user | |||
# committer is now mapped | |||
c = Changeset.create!(:repository => @repository, :committer => 'foo', :committed_on => Time.now, :revision => 101, :comments => 'Another commit by foo.') | |||
assert_equal User.find(2), c.user | |||
end | |||
end | |||
def test_auto_user_mapping_by_username | |||
c = Changeset.create!(:repository => @repository, :committer => 'jsmith', :committed_on => Time.now, :revision => 100, :comments => 'Committed by john.') | |||
assert_equal User.find(2), c.user | |||
end | |||
def test_auto_user_mapping_by_email | |||
c = Changeset.create!(:repository => @repository, :committer => 'john <jsmith@somenet.foo>', :committed_on => Time.now, :revision => 100, :comments => 'Committed by john.') | |||
assert_equal User.find(2), c.user | |||
end | |||
end |