Commit be43b9b3 authored by jplang's avatar jplang

Merged rails-3.2 branch.

git-svn-id: https://svn.redmine.org/redmine/trunk@9528 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent a631c49b
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
/config/database.yml /config/database.yml
/config/email.yml /config/email.yml
/config/initializers/session_store.rb /config/initializers/session_store.rb
/config/initializers/secret_token.rb
/coverage /coverage
/db/*.db /db/*.db
/db/*.sqlite3 /db/*.sqlite3
......
...@@ -7,6 +7,7 @@ config/configuration.yml ...@@ -7,6 +7,7 @@ config/configuration.yml
config/database.yml config/database.yml
config/email.yml config/email.yml
config/initializers/session_store.rb config/initializers/session_store.rb
config/initializers/secret_token.rb
coverage coverage
db/*.db db/*.db
db/*.sqlite3 db/*.sqlite3
......
source :rubygems source 'http://rubygems.org'
gem "rails", "2.3.14" gem 'rails', '3.2.3'
gem "i18n", "~> 0.4.2" gem 'prototype-rails', '3.2.1'
gem "i18n", "~> 0.6.0"
gem "coderay", "~> 1.0.6" gem "coderay", "~> 1.0.6"
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
gem "tzinfo", "~> 0.3.31" gem "tzinfo", "~> 0.3.31"
gem "builder"
# Optional gem for LDAP authentication # Optional gem for LDAP authentication
group :ldap do group :ldap do
...@@ -14,6 +16,7 @@ end ...@@ -14,6 +16,7 @@ end
# Optional gem for OpenID authentication # Optional gem for OpenID authentication
group :openid do group :openid do
gem "ruby-openid", "~> 2.1.4", :require => "openid" gem "ruby-openid", "~> 2.1.4", :require => "openid"
gem "rack-openid"
end end
# Optional gem for exporting the gantt to a PNG file, not supported with jruby # Optional gem for exporting the gantt to a PNG file, not supported with jruby
...@@ -45,7 +48,7 @@ end ...@@ -45,7 +48,7 @@ end
platforms :mri_19, :mingw_19 do platforms :mri_19, :mingw_19 do
group :mysql do group :mysql do
gem "mysql2", "~> 0.2.7" gem "mysql2", "~> 0.3.11"
end end
end end
...@@ -69,8 +72,9 @@ group :development do ...@@ -69,8 +72,9 @@ group :development do
gem "rdoc", ">= 2.4.2" gem "rdoc", ">= 2.4.2"
end end
group :test do group :test do
gem "shoulda", "~> 2.10.3" gem "shoulda"
gem "mocha" gem "mocha"
end end
......
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake, # Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/switchtower.rake, and they will automatically be available to Rake. # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require(File.join(File.dirname(__FILE__), 'config', 'boot')) require File.expand_path('../config/application', __FILE__)
require 'rake' RedmineApp::Application.load_tasks
require 'rake/testtask'
begin
require 'rdoc/task'
rescue LoadError
# RDoc is not available
end
require 'tasks/rails'
...@@ -22,9 +22,12 @@ class Unauthorized < Exception; end ...@@ -22,9 +22,12 @@ class Unauthorized < Exception; end
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
include Redmine::I18n include Redmine::I18n
class_attribute :accept_api_auth_actions
class_attribute :accept_rss_auth_actions
class_attribute :model_object
layout 'base' layout 'base'
exempt_from_layout 'builder', 'rsb'
protect_from_forgery protect_from_forgery
def handle_unverified_request def handle_unverified_request
...@@ -68,7 +71,6 @@ class ApplicationController < ActionController::Base ...@@ -68,7 +71,6 @@ class ApplicationController < ActionController::Base
end end
before_filter :user_setup, :check_if_login_required, :set_localization before_filter :user_setup, :check_if_login_required, :set_localization
filter_parameter_logging :password
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
rescue_from ::Unauthorized, :with => :deny_access rescue_from ::Unauthorized, :with => :deny_access
...@@ -77,10 +79,6 @@ class ApplicationController < ActionController::Base ...@@ -77,10 +79,6 @@ class ApplicationController < ActionController::Base
include Redmine::MenuManager::MenuController include Redmine::MenuManager::MenuController
helper Redmine::MenuManager::MenuHelper helper Redmine::MenuManager::MenuHelper
Redmine::Scm::Base.all.each do |scm|
require_dependency "repository/#{scm.underscore}"
end
def user_setup def user_setup
# Check the settings cache for each request # Check the settings cache for each request
Setting.check_cache Setting.check_cache
...@@ -242,7 +240,7 @@ class ApplicationController < ActionController::Base ...@@ -242,7 +240,7 @@ class ApplicationController < ActionController::Base
end end
def find_model_object def find_model_object
model = self.class.read_inheritable_attribute('model_object') model = self.class.model_object
if model if model
@object = model.find(params[:id]) @object = model.find(params[:id])
self.instance_variable_set('@' + controller_name.singularize, @object) if @object self.instance_variable_set('@' + controller_name.singularize, @object) if @object
...@@ -252,7 +250,7 @@ class ApplicationController < ActionController::Base ...@@ -252,7 +250,7 @@ class ApplicationController < ActionController::Base
end end
def self.model_object(model) def self.model_object(model)
write_inheritable_attribute('model_object', model) self.model_object = model
end end
# Filter for bulk issue operations # Filter for bulk issue operations
...@@ -388,9 +386,9 @@ class ApplicationController < ActionController::Base ...@@ -388,9 +386,9 @@ class ApplicationController < ActionController::Base
def self.accept_rss_auth(*actions) def self.accept_rss_auth(*actions)
if actions.any? if actions.any?
write_inheritable_attribute('accept_rss_auth_actions', actions) self.accept_rss_auth_actions = actions
else else
read_inheritable_attribute('accept_rss_auth_actions') || [] self.accept_rss_auth_actions || []
end end
end end
...@@ -400,9 +398,9 @@ class ApplicationController < ActionController::Base ...@@ -400,9 +398,9 @@ class ApplicationController < ActionController::Base
def self.accept_api_auth(*actions) def self.accept_api_auth(*actions)
if actions.any? if actions.any?
write_inheritable_attribute('accept_api_auth_actions', actions) self.accept_api_auth_actions = actions
else else
read_inheritable_attribute('accept_api_auth_actions') || [] self.accept_api_auth_actions || []
end end
end end
...@@ -523,26 +521,12 @@ class ApplicationController < ActionController::Base ...@@ -523,26 +521,12 @@ class ApplicationController < ActionController::Base
else else
@error_messages = objects.errors.full_messages @error_messages = objects.errors.full_messages
end end
render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => false render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => nil
end
# Overrides #default_template so that the api template
# is used automatically if it exists
def default_template(action_name = self.action_name)
if api_request?
begin
return self.view_paths.find_template(default_template_name(action_name), 'api')
rescue ::ActionView::MissingTemplate
# the api template was not found
# fallback to the default behaviour
end
end
super
end end
# Overrides #pick_layout so that #render with no arguments # Overrides #_include_layout? so that #render with no arguments
# doesn't use the layout for api requests # doesn't use the layout for api requests
def pick_layout(*args) def _include_layout?(*args)
api_request? ? nil : super api_request? ? false : super
end end
end end
...@@ -95,10 +95,11 @@ class MessagesController < ApplicationController ...@@ -95,10 +95,11 @@ class MessagesController < ApplicationController
# Delete a messages # Delete a messages
def destroy def destroy
(render_403; return false) unless @message.destroyable_by?(User.current) (render_403; return false) unless @message.destroyable_by?(User.current)
r = @message.to_param
@message.destroy @message.destroy
redirect_to @message.parent.nil? ? redirect_to @message.parent.nil? ?
{ :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } : { :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } :
{ :action => 'show', :id => @message.parent, :r => @message } { :action => 'show', :id => @message.parent, :r => r }
end end
def quote def quote
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
require 'SVG/Graph/Bar' require 'SVG/Graph/Bar'
require 'SVG/Graph/BarHorizontal' require 'SVG/Graph/BarHorizontal'
require 'digest/sha1' require 'digest/sha1'
require 'redmine/scm/adapters/abstract_adapter'
class ChangesetNotFound < Exception; end class ChangesetNotFound < Exception; end
class InvalidRevisionParam < Exception; end class InvalidRevisionParam < Exception; end
...@@ -307,8 +308,7 @@ class RepositoriesController < ApplicationController ...@@ -307,8 +308,7 @@ class RepositoriesController < ApplicationController
@repository = @project.repository @repository = @project.repository
end end
(render_404; return false) unless @repository (render_404; return false) unless @repository
@path = params[:path].join('/') unless params[:path].nil? @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s
@path ||= ''
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip
@rev_to = params[:rev_to] @rev_to = params[:rev_to]
...@@ -343,15 +343,15 @@ class RepositoriesController < ApplicationController ...@@ -343,15 +343,15 @@ class RepositoriesController < ApplicationController
@date_to = Date.today @date_to = Date.today
@date_from = @date_to << 11 @date_from = @date_to << 11
@date_from = Date.civil(@date_from.year, @date_from.month, 1) @date_from = Date.civil(@date_from.year, @date_from.month, 1)
commits_by_day = repository.changesets.count( commits_by_day = Changeset.count(
:all, :group => :commit_date, :all, :group => :commit_date,
:conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to]) :conditions => ["repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
commits_by_month = [0] * 12 commits_by_month = [0] * 12
commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last } commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
changes_by_day = repository.changes.count( changes_by_day = Change.count(
:all, :group => :commit_date, :all, :group => :commit_date, :include => :changeset,
:conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to]) :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
changes_by_month = [0] * 12 changes_by_month = [0] * 12
changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last } changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
...@@ -384,10 +384,10 @@ class RepositoriesController < ApplicationController ...@@ -384,10 +384,10 @@ class RepositoriesController < ApplicationController
end end
def graph_commits_per_author(repository) def graph_commits_per_author(repository)
commits_by_author = repository.changesets.count(:all, :group => :committer) commits_by_author = Changeset.count(:all, :group => :committer, :conditions => ["repository_id = ?", repository.id])
commits_by_author.to_a.sort! {|x, y| x.last <=> y.last} commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
changes_by_author = repository.changes.count(:all, :group => :committer) changes_by_author = Change.count(:all, :group => :committer, :include => :changeset, :conditions => ["#{Changeset.table_name}.repository_id = ?", repository.id])
h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o} h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
fields = commits_by_author.collect {|r| r.first} fields = commits_by_author.collect {|r| r.first}
......
...@@ -109,7 +109,7 @@ private ...@@ -109,7 +109,7 @@ private
@watched = klass.find(params[:object_id]) @watched = klass.find(params[:object_id])
@project = @watched.project @project = @watched.project
elsif params[:project_id] elsif params[:project_id]
@project = Project.visible.find(params[:project_id]) @project = Project.visible.find_by_param(params[:project_id])
end end
rescue rescue
render_404 render_404
......
...@@ -163,6 +163,8 @@ class WikiController < ApplicationController ...@@ -163,6 +163,8 @@ class WikiController < ApplicationController
# Optimistic locking exception # Optimistic locking exception
flash.now[:error] = l(:notice_locking_conflict) flash.now[:error] = l(:notice_locking_conflict)
render :action => 'edit' render :action => 'edit'
rescue ActiveRecord::RecordNotSaved
render :action => 'edit'
end end
# rename a page # rename a page
......
...@@ -930,6 +930,9 @@ module ApplicationHelper ...@@ -930,6 +930,9 @@ module ApplicationHelper
def labelled_form_for(*args, &proc) def labelled_form_for(*args, &proc)
args << {} unless args.last.is_a?(Hash) args << {} unless args.last.is_a?(Hash)
options = args.last options = args.last
if args.first.is_a?(Symbol)
options.merge!(:as => args.shift)
end
options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
form_for(*args, &proc) form_for(*args, &proc)
end end
...@@ -1060,7 +1063,7 @@ module ApplicationHelper ...@@ -1060,7 +1063,7 @@ module ApplicationHelper
# +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>') # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
def avatar(user, options = { }) def avatar(user, options = { })
if Setting.gravatar_enabled? if Setting.gravatar_enabled?
options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default}) options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default})
email = nil email = nil
if user.respond_to?(:mail) if user.respond_to?(:mail)
email = user.mail email = user.mail
...@@ -1079,7 +1082,7 @@ module ApplicationHelper ...@@ -1079,7 +1082,7 @@ module ApplicationHelper
# Returns the javascript tags that are included in the html layout head # Returns the javascript tags that are included in the html layout head
def javascript_heads def javascript_heads
tags = javascript_include_tag(:defaults) tags = javascript_include_tag('prototype', 'effects', 'dragdrop', 'controls', 'rails', 'application')
unless User.current.pref.warn_on_leaving_unsaved == '0' unless User.current.pref.warn_on_leaving_unsaved == '0'
tags << "\n".html_safe + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") tags << "\n".html_safe + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });")
end end
......
...@@ -21,14 +21,14 @@ module WikiHelper ...@@ -21,14 +21,14 @@ module WikiHelper
def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0) def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0)
pages = pages.group_by(&:parent) unless pages.is_a?(Hash) pages = pages.group_by(&:parent) unless pages.is_a?(Hash)
s = '' s = ''.html_safe
if pages.has_key?(parent) if pages.has_key?(parent)
pages[parent].each do |page| pages[parent].each do |page|
attrs = "value='#{page.id}'" attrs = "value='#{page.id}'"
attrs << " selected='selected'" if selected == page attrs << " selected='selected'" if selected == page
indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : nil indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : ''
s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" + s << content_tag('option', (indent + h(page.pretty_title)).html_safe, :value => page.id.to_s, :selected => selected == page) +
wiki_page_options_for_select(pages, selected, page, level + 1) wiki_page_options_for_select(pages, selected, page, level + 1)
end end
end end
......
...@@ -80,7 +80,7 @@ class CustomField < ActiveRecord::Base ...@@ -80,7 +80,7 @@ class CustomField < ActiveRecord::Base
when 'bool' when 'bool'
[[l(:general_text_Yes), '1'], [l(:general_text_No), '0']] [[l(:general_text_Yes), '1'], [l(:general_text_No), '0']]
else else
read_possible_values_utf8_encoded || [] possible_values || []
end end
end end
...@@ -91,14 +91,20 @@ class CustomField < ActiveRecord::Base ...@@ -91,14 +91,20 @@ class CustomField < ActiveRecord::Base
when 'bool' when 'bool'
['1', '0'] ['1', '0']
else else
read_possible_values_utf8_encoded values = super()
if values.is_a?(Array)
values.each do |value|
value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
end
end
values
end end
end end
# Makes possible_values accept a multiline string # Makes possible_values accept a multiline string
def possible_values=(arg) def possible_values=(arg)
if arg.is_a?(Array) if arg.is_a?(Array)
write_attribute(:possible_values, arg.compact.collect(&:strip).select {|v| !v.blank?}) super(arg.compact.collect(&:strip).select {|v| !v.blank?})
else else
self.possible_values = arg.to_s.split(/[\n\r]+/) self.possible_values = arg.to_s.split(/[\n\r]+/)
end end
...@@ -218,14 +224,4 @@ class CustomField < ActiveRecord::Base ...@@ -218,14 +224,4 @@ class CustomField < ActiveRecord::Base
end end
errs errs
end end
def read_possible_values_utf8_encoded
values = read_attribute(:possible_values)
if values.is_a?(Array)
values.each do |value|