[DRE-commits] [redmine] 01/26: Imported Upstream version 3.0~20140825

Antonio Terceiro terceiro at moszumanska.debian.org
Sun Sep 14 17:54:45 UTC 2014


This is an automated email from the git hooks/post-receive script.

terceiro pushed a commit to branch master
in repository redmine.

commit 45b5122bb4fd7d3b868ad6518bd1da95ca8a3b98
Author: Antonio Terceiro <terceiro at debian.org>
Date:   Mon Aug 25 21:03:02 2014 -0300

    Imported Upstream version 3.0~20140825
---
 .travis.run-test.sh                                |    3 +
 .travis.yml                                        |    8 +-
 Gemfile                                            |   45 +-
 app/controllers/admin_controller.rb                |    2 +-
 app/controllers/application_controller.rb          |    2 +-
 app/controllers/attachments_controller.rb          |    6 +-
 app/controllers/auto_completes_controller.rb       |    2 +-
 app/controllers/boards_controller.rb               |    9 +-
 app/controllers/documents_controller.rb            |    6 +-
 app/controllers/enumerations_controller.rb         |    6 +-
 app/controllers/files_controller.rb                |    6 +-
 app/controllers/groups_controller.rb               |   17 +-
 app/controllers/issue_categories_controller.rb     |    2 +-
 app/controllers/issue_statuses_controller.rb       |    2 +-
 app/controllers/issues_controller.rb               |   21 +-
 app/controllers/journals_controller.rb             |    1 -
 app/controllers/members_controller.rb              |    7 +-
 app/controllers/messages_controller.rb             |    4 +-
 app/controllers/my_controller.rb                   |    4 +-
 app/controllers/news_controller.rb                 |    2 +-
 app/controllers/project_enumerations_controller.rb |    2 +-
 app/controllers/projects_controller.rb             |   26 +-
 app/controllers/queries_controller.rb              |    3 +-
 app/controllers/reports_controller.rb              |    2 +-
 app/controllers/repositories_controller.rb         |    8 +-
 app/controllers/roles_controller.rb                |   10 +-
 app/controllers/search_controller.rb               |    2 +-
 app/controllers/sys_controller.rb                  |    5 +-
 app/controllers/timelog_controller.rb              |   10 +-
 app/controllers/trackers_controller.rb             |    6 +-
 app/controllers/users_controller.rb                |    8 +-
 app/controllers/versions_controller.rb             |    8 +-
 app/controllers/watchers_controller.rb             |    4 +-
 app/controllers/wiki_controller.rb                 |    6 +-
 app/controllers/workflows_controller.rb            |  107 +-
 app/helpers/application_helper.rb                  |   28 +-
 app/helpers/groups_helper.rb                       |    2 +-
 app/helpers/issues_helper.rb                       |    6 +-
 app/helpers/members_helper.rb                      |    2 +-
 app/helpers/my_helper.rb                           |   21 +-
 app/helpers/projects_helper.rb                     |   16 +-
 app/helpers/queries_helper.rb                      |   34 +-
 app/helpers/settings_helper.rb                     |   24 +-
 app/helpers/sort_helper.rb                         |    3 +-
 app/helpers/timelog_helper.rb                      |    2 +-
 app/helpers/workflows_helper.rb                    |   62 +-
 app/models/attachment.rb                           |   15 +-
 app/models/auth_source.rb                          |    1 +
 app/models/auth_source_ldap.rb                     |    4 -
 app/models/board.rb                                |    9 +-
 app/models/change.rb                               |    1 +
 app/models/changeset.rb                            |    9 +-
 app/models/comment.rb                              |    1 +
 app/models/custom_field.rb                         |    5 +-
 app/models/custom_value.rb                         |    1 +
 app/models/document.rb                             |   10 +-
 app/models/enabled_module.rb                       |    1 +
 app/models/enumeration.rb                          |   12 +-
 app/models/group.rb                                |    4 +-
 app/models/issue.rb                                |  140 +--
 app/models/issue_category.rb                       |    1 +
 app/models/issue_custom_field.rb                   |    2 +-
 app/models/issue_query.rb                          |   34 +-
 app/models/issue_status.rb                         |    3 +-
 app/models/journal.rb                              |   26 +-
 app/models/journal_detail.rb                       |    1 +
 app/models/mail_handler.rb                         |   17 +-
 app/models/member.rb                               |    3 +-
 app/models/member_role.rb                          |    1 +
 app/models/message.rb                              |    9 +-
 app/models/news.rb                                 |   14 +-
 app/models/principal.rb                            |   18 +-
 app/models/project.rb                              |   71 +-
 app/models/query.rb                                |   49 +-
 app/models/repository.rb                           |   16 +-
 app/models/repository/cvs.rb                       |   10 +-
 app/models/repository/git.rb                       |    2 +-
 app/models/repository/mercurial.rb                 |    7 +-
 app/models/repository/subversion.rb                |    2 +-
 app/models/role.rb                                 |    2 +-
 app/models/setting.rb                              |    2 +
 app/models/time_entry.rb                           |   14 +-
 app/models/time_entry_query.rb                     |    5 +-
 app/models/token.rb                                |    1 +
 app/models/tracker.rb                              |    4 +-
 app/models/user.rb                                 |   25 +-
 app/models/version.rb                              |    7 +-
 app/models/watcher.rb                              |    1 +
 app/models/wiki.rb                                 |    3 +-
 app/models/wiki_content.rb                         |   19 +-
 app/models/wiki_page.rb                            |   13 +-
 app/models/wiki_redirect.rb                        |    1 +
 app/models/workflow_permission.rb                  |   43 +-
 app/models/workflow_rule.rb                        |    3 +-
 app/models/workflow_transition.rb                  |   71 +-
 app/views/groups/_memberships.html.erb             |    2 +-
 app/views/groups/index.html.erb                    |    5 +-
 app/views/issues/bulk_edit.html.erb                |    2 +-
 app/views/journals/new.js.erb                      |    2 +-
 app/views/layouts/base.html.erb                    |    2 +-
 app/views/projects/_form.html.erb                  |    2 +-
 app/views/projects/settings/_members.html.erb      |    2 +-
 app/views/repositories/_revisions.html.erb         |    4 +-
 app/views/search/index.html.erb                    |    4 +-
 app/views/timelog/_form.html.erb                   |    6 +-
 app/views/users/_memberships.html.erb              |    2 +-
 app/views/wiki/destroy.html.erb                    |    2 +-
 app/views/wiki/edit.html.erb                       |    2 +-
 app/views/wiki/history.html.erb                    |    2 +-
 app/views/wiki/rename.html.erb                     |    2 +-
 app/views/workflows/_form.html.erb                 |    5 +-
 app/views/workflows/edit.html.erb                  |   33 +-
 app/views/workflows/permissions.html.erb           |   37 +-
 {script => bin}/about                              |    0
 bin/bundle                                         |    3 +
 bin/rails                                          |    4 +
 bin/rake                                           |    4 +
 config/application.rb                              |    9 +-
 config/boot.rb                                     |    2 -
 config/database.yml.example                        |    3 +-
 config/environment.rb                              |    6 +-
 config/environments/development.rb                 |   18 +-
 config/environments/production.rb                  |   34 +-
 config/environments/test.rb                        |   17 +-
 config/environments/test_pgsql.rb                  |    1 +
 config/environments/test_sqlite3.rb                |    1 +
 config/initializers/10-patches.rb                  |   72 +-
 config/initializers/30-redmine.rb                  |    2 +
 config/locales/ar.yml                              |    1 +
 config/locales/az.yml                              |    1 +
 config/locales/bg.yml                              |    1 +
 config/locales/bs.yml                              |    1 +
 config/locales/ca.yml                              |    1 +
 config/locales/cs.yml                              |    1 +
 config/locales/da.yml                              |    1 +
 config/locales/de.yml                              |    1 +
 config/locales/el.yml                              |    1 +
 config/locales/en-GB.yml                           |    1 +
 config/locales/en.yml                              |    1 +
 config/locales/es.yml                              |    1 +
 config/locales/et.yml                              |    1 +
 config/locales/eu.yml                              |    1 +
 config/locales/fa.yml                              |  632 ++++++------
 config/locales/fi.yml                              |    1 +
 config/locales/fr.yml                              |  181 ++--
 config/locales/gl.yml                              |    1 +
 config/locales/he.yml                              |    1 +
 config/locales/hr.yml                              |    1 +
 config/locales/hu.yml                              |    1 +
 config/locales/id.yml                              |    1 +
 config/locales/it.yml                              |    1 +
 config/locales/ja.yml                              |   45 +-
 config/locales/ko.yml                              |    1 +
 config/locales/lt.yml                              |    1 +
 config/locales/lv.yml                              |    1 +
 config/locales/mk.yml                              |    1 +
 config/locales/mn.yml                              |    1 +
 config/locales/nl.yml                              |    1 +
 config/locales/no.yml                              |    1 +
 config/locales/pl.yml                              |    1 +
 config/locales/pt-BR.yml                           |    1 +
 config/locales/pt.yml                              |    1 +
 config/locales/ro.yml                              |    1 +
 config/locales/ru.yml                              |    1 +
 config/locales/sk.yml                              |    1 +
 config/locales/sl.yml                              |    1 +
 config/locales/sq.yml                              |    1 +
 config/locales/sr-YU.yml                           |    1 +
 config/locales/sr.yml                              |    1 +
 config/locales/sv.yml                              |    1 +
 config/locales/th.yml                              |    1 +
 config/locales/tr.yml                              |    1 +
 config/locales/uk.yml                              |    1 +
 config/locales/vi.yml                              |    1 +
 config/locales/zh-TW.yml                           |   29 +-
 config/locales/zh.yml                              |    1 +
 config/preinitializer.rb                           |   20 -
 config/routes.rb                                   |   16 +-
 db/migrate/001_setup.rb                            |    5 +-
 ...calendar_and_gantt_modules_where_appropriate.rb |    2 +-
 doc/CHANGELOG                                      |   14 +-
 doc/INSTALL                                        |    5 +-
 .../lib/acts_as_activity_provider.rb               |    6 +-
 .../acts_as_attachable/lib/acts_as_attachable.rb   |    5 +-
 .../lib/acts_as_customizable.rb                    |    7 +-
 lib/plugins/acts_as_event/lib/acts_as_event.rb     |    2 +-
 .../acts_as_searchable/lib/acts_as_searchable.rb   |   15 +-
 .../acts_as_tree/lib/active_record/acts/tree.rb    |    2 +-
 .../acts_as_watchable/lib/acts_as_watchable.rb     |    2 +-
 lib/redcloth3.rb                                   |    2 +-
 lib/redmine.rb                                     |    7 +-
 lib/redmine/access_control.rb                      |    4 +-
 lib/redmine/codeset_util.rb                        |  147 +--
 lib/redmine/configuration.rb                       |    5 +-
 lib/redmine/core_ext/active_record.rb              |   25 -
 lib/redmine/core_ext/string/conversions.rb         |    7 -
 lib/redmine/export/pdf.rb                          |   34 +-
 lib/redmine/field_format.rb                        |    3 +-
 lib/redmine/helpers/gantt.rb                       |    4 +-
 lib/redmine/hook.rb                                |    4 +-
 lib/redmine/i18n.rb                                |    2 +-
 lib/redmine/imap.rb                                |    2 +-
 lib/redmine/menu_manager.rb                        |    2 +-
 lib/redmine/notifiable.rb                          |    1 +
 lib/redmine/plugin.rb                              |    8 +-
 lib/redmine/pop3.rb                                |   16 +-
 lib/redmine/scm/adapters/abstract_adapter.rb       |   27 +-
 lib/redmine/scm/adapters/bazaar_adapter.rb         |    7 +-
 lib/redmine/scm/adapters/cvs_adapter.rb            |    7 +-
 lib/redmine/scm/adapters/darcs_adapter.rb          |    5 +-
 lib/redmine/scm/adapters/git_adapter.rb            |   10 +-
 lib/redmine/scm/adapters/mercurial_adapter.rb      |   22 +-
 lib/redmine/scm/adapters/subversion_adapter.rb     |   25 +-
 lib/redmine/unified_diff.rb                        |   20 +-
 lib/redmine/version.rb                             |    2 +-
 lib/redmine/views/labelled_form_builder.rb         |   16 +-
 lib/redmine/wiki_formatting.rb                     |   14 +-
 lib/tasks/ci.rake                                  |    6 +-
 lib/tasks/ciphering.rake                           |    4 +-
 lib/tasks/email.rake                               |   14 +-
 lib/tasks/locales.rake                             |    3 -
 lib/tasks/migrate_from_mantis.rake                 |    8 +-
 lib/tasks/migrate_from_trac.rake                   |   15 +-
 lib/tasks/redmine.rake                             |    3 +-
 lib/tasks/testing.rake                             |   16 +-
 public/javascripts/application.js                  |   20 +-
 public/javascripts/context_menu.js                 |   10 +-
 public/javascripts/gantt.js                        |    4 +-
 .../jquery-1.11.1-ui-1.11.0-ujs-3.1.1.js           |   21 +
 .../javascripts/jquery-1.8.3-ui-1.9.2-ujs-2.0.3.js |   11 -
 public/stylesheets/application.css                 |    8 +-
 .../stylesheets/jquery/images/animated-overlay.gif |  Bin 0 -> 1738 bytes
 .../ui-bg_diagonals-thick_18_b81900_40x40.png      |  Bin 260 -> 418 bytes
 .../ui-bg_diagonals-thick_20_666666_40x40.png      |  Bin 251 -> 312 bytes
 .../jquery/images/ui-bg_flat_10_000000_40x100.png  |  Bin 178 -> 205 bytes
 .../jquery/images/ui-bg_glass_100_eef5fd_1x400.png |  Bin 113 -> 345 bytes
 .../jquery/images/ui-bg_glass_100_f6f6f6_1x400.png |  Bin 104 -> 262 bytes
 .../jquery/images/ui-bg_glass_65_ffffff_1x400.png  |  Bin 105 -> 207 bytes
 .../images/ui-bg_gloss-wave_35_759fcf_500x100.png  |  Bin 3945 -> 5772 bytes
 .../ui-bg_highlight-soft_100_eeeeee_1x100.png      |  Bin 90 -> 278 bytes
 .../ui-bg_highlight-soft_75_759fcf_1x100.png       |  Bin 126 -> 343 bytes
 .../jquery/images/ui-icons_222222_256x240.png      |  Bin 4369 -> 6922 bytes
 .../jquery/images/ui-icons_759fcf_256x240.png      |  Bin 4369 -> 4549 bytes
 .../jquery/images/ui-icons_ffd27a_256x240.png      |  Bin 4369 -> 4549 bytes
 .../jquery/images/ui-icons_ffffff_256x240.png      |  Bin 4369 -> 6299 bytes
 public/stylesheets/jquery/jquery-ui-1.11.0.css     |    7 +
 public/stylesheets/jquery/jquery-ui-1.9.2.css      |    5 -
 script/about                                       |    6 +-
 script/rails                                       |    6 +-
 test/fixtures/mail_handler/gmail-iso8859-2.eml     |   11 +
 .../mail_handler/quoted_printable_utf8.eml         |   19 +
 test/functional/account_controller_test.rb         |   12 +-
 test/functional/activities_controller_test.rb      |   12 +-
 test/functional/admin_controller_test.rb           |    3 +-
 test/functional/attachments_controller_test.rb     |   30 +-
 test/functional/calendars_controller_test.rb       |   15 +-
 test/functional/context_menus_controller_test.rb   |   14 +-
 test/functional/custom_fields_controller_test.rb   |    2 +-
 test/functional/groups_controller_test.rb          |    8 +-
 test/functional/issues_controller_test.rb          |   55 +-
 .../issues_custom_fields_visibility_test.rb        |    4 +-
 test/functional/members_controller_test.rb         |    2 +-
 test/functional/messages_controller_test.rb        |    4 +-
 test/functional/my_controller_test.rb              |    2 +-
 .../repositories_bazaar_controller_test.rb         |   54 +-
 .../functional/repositories_cvs_controller_test.rb |    2 +-
 .../repositories_filesystem_controller_test.rb     |   12 +-
 .../functional/repositories_git_controller_test.rb |   45 +-
 .../repositories_mercurial_controller_test.rb      |   21 +-
 test/functional/roles_controller_test.rb           |    4 +-
 test/functional/search_controller_test.rb          |    5 +-
 test/functional/settings_controller_test.rb        |   12 +-
 .../time_entry_reports_controller_test.rb          |   51 +-
 test/functional/timelog_controller_test.rb         |   18 +-
 .../timelog_custom_fields_visibility_test.rb       |    8 +-
 test/functional/welcome_controller_test.rb         |    4 +-
 test/functional/wiki_controller_test.rb            |    8 +-
 test/functional/workflows_controller_test.rb       |  138 +--
 test/integration/account_test.rb                   |    9 +-
 test/integration/admin_test.rb                     |    2 +-
 test/integration/api_test/authentication_test.rb   |    7 +-
 test/integration/api_test/memberships_test.rb      |    2 +-
 test/integration/api_test/projects_test.rb         |   12 +-
 test/integration/application_test.rb               |    2 +-
 test/integration/attachments_test.rb               |    2 +-
 test/integration/feeds_test.rb                     |    2 +-
 test/integration/issues_test.rb                    |    2 +-
 test/integration/layout_test.rb                    |    2 +-
 test/integration/lib/redmine/hook_test.rb          |    4 +-
 test/integration/lib/redmine/menu_manager_test.rb  |    2 +-
 test/integration/lib/redmine/themes_test.rb        |    2 +-
 test/integration/projects_test.rb                  |    2 +-
 test/integration/repositories_git_test.rb          |    2 +-
 test/integration/routing/account_test.rb           |    2 +-
 test/integration/routing/activities_test.rb        |    2 +-
 test/integration/routing/admin_test.rb             |    2 +-
 test/integration/routing/attachments_test.rb       |    2 +-
 test/integration/routing/auth_sources_test.rb      |    2 +-
 test/integration/routing/auto_completes_test.rb    |    2 +-
 test/integration/routing/boards_test.rb            |    2 +-
 test/integration/routing/calendars_test.rb         |    2 +-
 test/integration/routing/comments_test.rb          |    2 +-
 test/integration/routing/context_menus_test.rb     |    2 +-
 test/integration/routing/custom_fields_test.rb     |    2 +-
 test/integration/routing/documents_test.rb         |    2 +-
 test/integration/routing/enumerations_test.rb      |    2 +-
 test/integration/routing/files_test.rb             |    2 +-
 test/integration/routing/gantts_test.rb            |    2 +-
 test/integration/routing/groups_test.rb            |    2 +-
 test/integration/routing/issue_categories_test.rb  |    2 +-
 test/integration/routing/issue_relations_test.rb   |    2 +-
 test/integration/routing/issue_statuses_test.rb    |    2 +-
 test/integration/routing/issues_test.rb            |    2 +-
 test/integration/routing/journals_test.rb          |    2 +-
 test/integration/routing/mail_handler_test.rb      |    2 +-
 test/integration/routing/members_test.rb           |    2 +-
 test/integration/routing/messages_test.rb          |    2 +-
 test/integration/routing/my_test.rb                |    2 +-
 test/integration/routing/news_test.rb              |    2 +-
 test/integration/routing/previews_test.rb          |    2 +-
 .../routing/project_enumerations_test.rb           |    2 +-
 test/integration/routing/projects_test.rb          |    2 +-
 test/integration/routing/queries_test.rb           |    2 +-
 test/integration/routing/reports_test.rb           |    2 +-
 test/integration/routing/repositories_test.rb      |    2 +-
 test/integration/routing/roles_test.rb             |    2 +-
 test/integration/routing/search_test.rb            |    2 +-
 test/integration/routing/settings_test.rb          |    2 +-
 test/integration/routing/sys_test.rb               |    2 +-
 test/integration/routing/timelog_test.rb           |    2 +-
 test/integration/routing/trackers_test.rb          |    2 +-
 test/integration/routing/users_test.rb             |    2 +-
 test/integration/routing/versions_test.rb          |    2 +-
 test/integration/routing/watchers_test.rb          |    2 +-
 test/integration/routing/welcome_test.rb           |    2 +-
 test/integration/routing/wiki_test.rb              |    4 +-
 test/integration/routing/wikis_test.rb             |    2 +-
 test/integration/routing/workflows_test.rb         |    2 +-
 test/integration/users_test.rb                     |    2 +-
 test/object_helpers.rb                             |    2 +-
 test/test_helper.rb                                |   20 +-
 test/unit/changeset_test.rb                        |   50 +-
 test/unit/custom_field_test.rb                     |   14 +-
 test/unit/enabled_module_test.rb                   |    2 +-
 test/unit/group_test.rb                            |    3 +-
 test/unit/helpers/application_helper_test.rb       |   50 +-
 test/unit/helpers/projects_helper_test.rb          |    1 +
 test/unit/initializers/patches_test.rb             |   42 +-
 test/unit/issue_nested_set_test.rb                 |   12 +-
 test/unit/issue_priority_test.rb                   |    8 +-
 test/unit/issue_status_test.rb                     |    2 +-
 test/unit/issue_test.rb                            |   46 +-
 test/unit/journal_observer_test.rb                 |   59 +-
 test/unit/journal_test.rb                          |   17 +-
 test/unit/lib/redmine/codeset_util_test.rb         |   65 +-
 test/unit/lib/redmine/export/pdf_test.rb           |   96 +-
 test/unit/lib/redmine/hook_test.rb                 |    1 +
 test/unit/lib/redmine/i18n_test.rb                 |   88 +-
 test/unit/lib/redmine/notifiable_test.rb           |    4 +-
 .../redmine/scm/adapters/bazaar_adapter_test.rb    |  343 ++++---
 .../lib/redmine/scm/adapters/cvs_adapter_test.rb   |  149 ++-
 .../lib/redmine/scm/adapters/darcs_adapter_test.rb |   71 +-
 .../lib/redmine/scm/adapters/git_adapter_test.rb   | 1028 ++++++++++----------
 .../redmine/scm/adapters/mercurial_adapter_test.rb |  781 ++++++++-------
 .../scm/adapters/subversion_adapter_test.rb        |   74 +-
 test/unit/lib/redmine/unified_diff_test.rb         |   36 +-
 .../lib/redmine/wiki_formatting/macros_test.rb     |   14 +-
 test/unit/mail_handler_test.rb                     |   89 +-
 test/unit/mailer_test.rb                           |    1 +
 test/unit/member_test.rb                           |    7 +-
 test/unit/principal_test.rb                        |    4 +-
 test/unit/project_nested_set_test.rb               |    7 +-
 test/unit/project_test.rb                          |    4 +-
 test/unit/query_test.rb                            |    8 +-
 test/unit/repository_bazaar_test.rb                |   74 +-
 test/unit/repository_cvs_test.rb                   |    6 +-
 test/unit/repository_darcs_test.rb                 |    3 +-
 test/unit/repository_filesystem_test.rb            |    3 +-
 test/unit/repository_git_test.rb                   |   25 +-
 test/unit/repository_mercurial_test.rb             |   25 +-
 test/unit/repository_subversion_test.rb            |    8 +-
 test/unit/repository_test.rb                       |    7 +-
 test/unit/role_test.rb                             |    8 +-
 test/unit/tracker_test.rb                          |    2 +-
 test/unit/user_test.rb                             |   13 +-
 test/unit/version_test.rb                          |    6 +-
 test/unit/wiki_test.rb                             |    3 +-
 test/unit/workflow_transition_test.rb              |   93 ++
 388 files changed, 3760 insertions(+), 3631 deletions(-)

diff --git a/.travis.run-test.sh b/.travis.run-test.sh
new file mode 100644
index 0000000..29ba321
--- /dev/null
+++ b/.travis.run-test.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+JRUBY_OPTS=-J-Xmx1024m bundle exec rake test:${TEST_SUITE}
diff --git a/.travis.yml b/.travis.yml
index 12a8666..3abeb22 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,10 +3,9 @@
 # You can also run tests on your environment.
 language: ruby
 rvm:
-  - 1.8.7
   - 1.9.3
-  - 2.0.0
-  - 2.1.0
+  - 2.0
+  - 2.1
   - jruby
 matrix:
   allow_failures:
@@ -33,6 +32,7 @@ script:
   - "bundle install"
   - "RUN_ON_NOT_OFFICIAL='' RUBY_VER=1.9 BRANCH=trunk bundle exec rake config/database.yml"
   - "bundle install"
-  - "JRUBY_OPTS=-J-Xmx1024m bundle exec rake ci"
+  - "bundle exec rake ci:setup"
+  - "sh .travis.run-test.sh"
 notifications:
   email: false
diff --git a/Gemfile b/Gemfile
index e7d98d5..62d7ff0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,13 +1,17 @@
 source 'https://rubygems.org'
 
-gem "rails", "3.2.19"
-gem "rake", "~> 10.1.1"
-gem "jquery-rails", "~> 2.0.2"
+gem "rails", "4.1.4"
+gem "jquery-rails", "~> 3.1.1"
 gem "coderay", "~> 1.1.0"
-gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
-gem "builder", "3.0.0"
+gem "builder", ">= 3.0.4"
+gem "request_store", "1.0.5"
 gem "mime-types"
-gem "awesome_nested_set", "2.1.6"
+gem "awesome_nested_set", ">= 3.0.0.rc.6"
+gem "protected_attributes"
+gem "actionpack-action_caching"
+
+# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
+gem 'tzinfo-data', platforms: [:mingw, :mswin, :jruby]
 
 # Optional gem for LDAP authentication
 group :ldap do
@@ -23,16 +27,12 @@ end
 platforms :mri, :mingw do
   # Optional gem for exporting the gantt to a PNG file, not supported with jruby
   group :rmagick do
-    # RMagick 2 supports ruby 1.9
-    # RMagick 1 would be fine for ruby 1.8 but Bundler does not support
-    # different requirements for the same gem on different platforms
     gem "rmagick", ">= 2.0.0"
   end
 
   # Optional Markdown support, not for JRuby
   group :markdown do
-    # TODO: upgrade to redcarpet 3.x when ruby1.8 support is dropped
-    gem "redcarpet", "~> 2.3.0"
+    gem "redcarpet", "~> 3.1.2"
   end
 end
 
@@ -57,7 +57,6 @@ if File.exist?(database_file)
         gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw]
         gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
       when 'mysql'
-        gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
         gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
       when /postgresql/
         gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
@@ -66,7 +65,7 @@ if File.exist?(database_file)
         gem "sqlite3", :platforms => [:mri, :mingw]
         gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
       when /sqlserver/
-        gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
+        gem "tiny_tds", "~> 0.6.2", :platforms => [:mri, :mingw]
         gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
       else
         warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
@@ -85,23 +84,21 @@ group :development do
 end
 
 group :test do
-  gem "shoulda", "~> 3.3.2"
-  gem "mocha", "~> 1.0.0", :require => 'mocha/api'
-  if RUBY_VERSION >= '1.9.3'
-    gem "capybara", "~> 2.1.0"
-    gem "selenium-webdriver"
-  end
+  gem "minitest"
+  gem "shoulda"
+  gem "shoulda-context"
+  gem "mocha", :require => 'mocha/api'
+  # For running UI tests
+  gem "capybara", "~> 2.1.0"
+  gem "selenium-webdriver"
 end
 
 local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
 if File.exists?(local_gemfile)
-  puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
-  instance_eval File.read(local_gemfile)
+  eval_gemfile local_gemfile
 end
 
 # Load plugins' Gemfiles
 Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
-  puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
-  #TODO: switch to "eval_gemfile file" when bundler >= 1.2.0 will be required (rails 4)
-  instance_eval File.read(file), file
+  eval_gemfile file
 end
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index c2d464d..b0e5ce6 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -34,7 +34,7 @@ class AdminController < ApplicationController
 
     scope = Project.status(@status).order('lft')
     scope = scope.like(params[:name]) if params[:name].present?
-    @projects = scope.all
+    @projects = scope.to_a
 
     render :action => "projects", :layout => false if request.xhr?
   end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 10e0ecb..7d55f0a 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -483,7 +483,7 @@ class ApplicationController < ActionController::Base
   end
 
   def render_feed(items, options={})
-    @items = items || []
+    @items = (items || []).to_a
     @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
     @items = @items.slice(0, Setting.feeds_limit.to_i)
     @title = options[:title] || Setting.app_title
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 18f0e0d..b7f856a 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -61,9 +61,9 @@ class AttachmentsController < ApplicationController
   end
 
   def thumbnail
-    if @attachment.thumbnailable? && thumbnail = @attachment.thumbnail(:size => params[:size])
-      if stale?(:etag => thumbnail)
-        send_file thumbnail,
+    if @attachment.thumbnailable? && tbnail = @attachment.thumbnail(:size => params[:size])
+      if stale?(:etag => tbnail)
+        send_file tbnail,
           :filename => filename_for_content_disposition(@attachment.filename),
           :type => detect_content_type(@attachment),
           :disposition => 'inline'
diff --git a/app/controllers/auto_completes_controller.rb b/app/controllers/auto_completes_controller.rb
index e9834eb..c40da89 100644
--- a/app/controllers/auto_completes_controller.rb
+++ b/app/controllers/auto_completes_controller.rb
@@ -26,7 +26,7 @@ class AutoCompletesController < ApplicationController
       if q.match(/\A#?(\d+)\z/)
         @issues << scope.find_by_id($1.to_i)
       end
-      @issues += scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%").order("#{Issue.table_name}.id DESC").limit(10).all
+      @issues += scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%").order("#{Issue.table_name}.id DESC").limit(10).to_a
       @issues.compact!
     end
     render :layout => false
diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb
index 1f1d473..04bdb56 100644
--- a/app/controllers/boards_controller.rb
+++ b/app/controllers/boards_controller.rb
@@ -25,7 +25,7 @@ class BoardsController < ApplicationController
   helper :watchers
 
   def index
-    @boards = @project.boards.includes(:project, :last_message => :author).all
+    @boards = @project.boards.preload(:project, :last_message => :author).to_a
     # show the board if there is only one
     if @boards.size == 1
       @board = @boards.first
@@ -45,12 +45,13 @@ class BoardsController < ApplicationController
         @topic_pages = Paginator.new @topic_count, per_page_option, params['page']
         @topics =  @board.topics.
           reorder("#{Message.table_name}.sticky DESC").
-          includes(:last_reply).
+          joins("LEFT OUTER JOIN #{Message.table_name} last_replies_messages ON last_replies_messages.id = #{Message.table_name}.last_reply_id").
+          references(:last_reply).
           limit(@topic_pages.per_page).
           offset(@topic_pages.offset).
           order(sort_clause).
           preload(:author, {:last_reply => :author}).
-          all
+          to_a
         @message = Message.new(:board => @board)
         render :action => 'show', :layout => !request.xhr?
       }
@@ -59,7 +60,7 @@ class BoardsController < ApplicationController
           reorder('created_on DESC').
           includes(:author, :board).
           limit(Setting.feeds_limit.to_i).
-          all
+          to_a
         render_feed(@messages, :title => "#{@project}: #{@board}")
       }
     end
diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb
index 43cfc25..47065f9 100644
--- a/app/controllers/documents_controller.rb
+++ b/app/controllers/documents_controller.rb
@@ -27,7 +27,7 @@ class DocumentsController < ApplicationController
 
   def index
     @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
-    documents = @project.documents.includes(:attachments, :category).all
+    documents = @project.documents.includes(:attachments, :category).to_a
     case @sort_by
     when 'date'
       @grouped = documents.group_by {|d| d.updated_on.to_date }
@@ -43,7 +43,7 @@ class DocumentsController < ApplicationController
   end
 
   def show
-    @attachments = @document.attachments.all
+    @attachments = @document.attachments.to_a
   end
 
   def new
@@ -69,7 +69,7 @@ class DocumentsController < ApplicationController
 
   def update
     @document.safe_attributes = params[:document]
-    if request.put? and @document.save
+    if @document.save
       flash[:notice] = l(:notice_successful_update)
       redirect_to document_path(@document)
     else
diff --git a/app/controllers/enumerations_controller.rb b/app/controllers/enumerations_controller.rb
index 65a5039..d8d9141 100644
--- a/app/controllers/enumerations_controller.rb
+++ b/app/controllers/enumerations_controller.rb
@@ -32,7 +32,7 @@ class EnumerationsController < ApplicationController
       format.api {
         @klass = Enumeration.get_subclass(params[:type])
         if @klass
-          @enumerations = @klass.shared.sorted.all
+          @enumerations = @klass.shared.sorted.to_a
         else
           render_404
         end
@@ -56,7 +56,7 @@ class EnumerationsController < ApplicationController
   end
 
   def update
-    if request.put? && @enumeration.update_attributes(params[:enumeration])
+    if @enumeration.update_attributes(params[:enumeration])
       flash[:notice] = l(:notice_successful_update)
       redirect_to enumerations_path
     else
@@ -75,7 +75,7 @@ class EnumerationsController < ApplicationController
       redirect_to enumerations_path
       return
     end
-    @enumerations = @enumeration.class.system.all - [@enumeration]
+    @enumerations = @enumeration.class.system.to_a - [@enumeration]
   end
 
   private
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index 6ba5c11..f3eb671 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -31,8 +31,10 @@ class FilesController < ApplicationController
                 'size' => "#{Attachment.table_name}.filesize",
                 'downloads' => "#{Attachment.table_name}.downloads"
 
-    @containers = [ Project.includes(:attachments).reorder(sort_clause).find(@project.id)]
-    @containers += @project.versions.includes(:attachments).reorder(sort_clause).all.sort.reverse
+    @containers = [Project.includes(:attachments).
+                     references(:attachments).reorder(sort_clause).find(@project.id)]
+    @containers += @project.versions.includes(:attachments).
+                    references(:attachments).reorder(sort_clause).to_a.sort.reverse
     render :layout => !request.xhr?
   end
 
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 2dbcd8a..673927f 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -25,10 +25,11 @@ class GroupsController < ApplicationController
   helper :custom_fields
 
   def index
-    @groups = Group.sorted.all
-
+    @groups = Group.sorted.to_a
     respond_to do |format|
-      format.html
+      format.html {
+        @user_count_by_group_id = user_count_by_group_id
+      }
       format.api
     end
   end
@@ -90,7 +91,7 @@ class GroupsController < ApplicationController
   end
 
   def add_users
-    @users = User.where(:id => (params[:user_id] || params[:user_ids])).all
+    @users = User.where(:id => (params[:user_id] || params[:user_ids])).to_a
     @group.users << @users if request.post?
     respond_to do |format|
       format.html { redirect_to edit_group_path(@group, :tab => 'users') }
@@ -138,4 +139,12 @@ class GroupsController < ApplicationController
   rescue ActiveRecord::RecordNotFound
     render_404
   end
+
+  def user_count_by_group_id
+    h = User.joins(:groups).group('group_id').count
+    h.keys.each do |key|
+      h[key.to_i] = h.delete(key)
+    end
+    h
+  end
 end
diff --git a/app/controllers/issue_categories_controller.rb b/app/controllers/issue_categories_controller.rb
index 6a95690..3c73510 100644
--- a/app/controllers/issue_categories_controller.rb
+++ b/app/controllers/issue_categories_controller.rb
@@ -27,7 +27,7 @@ class IssueCategoriesController < ApplicationController
   def index
     respond_to do |format|
       format.html { redirect_to_settings_in_projects }
-      format.api { @categories = @project.issue_categories.all }
+      format.api { @categories = @project.issue_categories.to_a }
     end
   end
 
diff --git a/app/controllers/issue_statuses_controller.rb b/app/controllers/issue_statuses_controller.rb
index d305ded..a6b72f3 100644
--- a/app/controllers/issue_statuses_controller.rb
+++ b/app/controllers/issue_statuses_controller.rb
@@ -29,7 +29,7 @@ class IssueStatusesController < ApplicationController
         render :action => "index", :layout => false if request.xhr?
       }
       format.api {
-        @issue_statuses = IssueStatus.order('position').all
+        @issue_statuses = IssueStatus.order('position').to_a
       }
     end
   end
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index de346c5..5623c3b 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -104,15 +104,16 @@ class IssuesController < ApplicationController
   end
 
   def show
-    @journals = @issue.journals.includes(:user, :details).reorder("#{Journal.table_name}.id ASC").all
+    @journals = @issue.journals.includes(:user, :details).
+                    references(:user, :details).
+                    reorder("#{Journal.table_name}.id ASC").to_a
     @journals.each_with_index {|j,i| j.indice = i+1}
     @journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
     Journal.preload_journals_details_custom_fields(@journals)
-    # TODO: use #select! when ruby1.8 support is dropped
-    @journals.reject! {|journal| !journal.notes? && journal.visible_details.empty?}
+    @journals.select! {|journal| journal.notes? || journal.visible_details.any?}
     @journals.reverse! if User.current.wants_comments_in_reverse_order?
 
-    @changesets = @issue.changesets.visible.all
+    @changesets = @issue.changesets.visible.to_a
     @changesets.reverse! if User.current.wants_comments_in_reverse_order?
 
     @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@@ -189,7 +190,7 @@ class IssuesController < ApplicationController
     rescue ActiveRecord::StaleObjectError
       @conflict = true
       if params[:last_journal_id]
-        @conflict_journals = @issue.journals_after(params[:last_journal_id]).all
+        @conflict_journals = @issue.journals_after(params[:last_journal_id]).to_a
         @conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
       end
     end
@@ -301,7 +302,7 @@ class IssuesController < ApplicationController
     else
       @saved_issues = @issues
       @unsaved_issues = unsaved_issues
-      @issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).all
+      @issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).to_a
       bulk_edit
       render :action => 'bulk_edit'
     end
@@ -375,7 +376,9 @@ class IssuesController < ApplicationController
   def update_issue_from_params
     @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
     @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
-    @time_entry.attributes = params[:time_entry]
+    if params[:time_entry]
+      @time_entry.attributes = params[:time_entry]
+    end
 
     @issue.init_journal(User.current)
 
@@ -422,7 +425,9 @@ class IssuesController < ApplicationController
     @issue.project = @project
     @issue.author ||= User.current
     # Tracker must be set before custom field values
-    @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
+    tracker_id = (params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id]
+    tracker = tracker_id.present? ? @project.trackers.find(tracker_id) : @project.trackers.first
+    @issue.tracker ||= tracker
     if @issue.tracker.nil?
       render_error l(:error_no_tracker_in_project)
       return false
diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb
index fe1c019..940a7b5 100644
--- a/app/controllers/journals_controller.rb
+++ b/app/controllers/journals_controller.rb
@@ -34,7 +34,6 @@ class JournalsController < ApplicationController
     retrieve_query
     sort_init 'id', 'desc'
     sort_update(@query.sortable_columns)
-
     if @query.valid?
       @journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC",
                                   :limit => 25)
diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb
index aca1367..ca5002a 100644
--- a/app/controllers/members_controller.rb
+++ b/app/controllers/members_controller.rb
@@ -32,7 +32,7 @@ class MembersController < ApplicationController
                     order("#{Member.table_name}.id").
                     limit(@limit).
                     offset(@offset).
-                    all
+                    to_a
     respond_to do |format|
       format.html { head 406 }
       format.api
@@ -63,7 +63,10 @@ class MembersController < ApplicationController
 
     respond_to do |format|
       format.html { redirect_to_settings_in_projects }
-      format.js { @members = members }
+      format.js {
+        @members = members
+        @member = Member.new
+      }
       format.api {
         @member = members.first
         if @member.valid?
diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb
index 0eb9f0b..aa0788a 100644
--- a/app/controllers/messages_controller.rb
+++ b/app/controllers/messages_controller.rb
@@ -43,10 +43,10 @@ class MessagesController < ApplicationController
     @reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page
     @replies =  @topic.children.
       includes(:author, :attachments, {:board => :project}).
-      reorder("#{Message.table_name}.created_on ASC").
+      reorder("#{Message.table_name}.created_on ASC, #{Message.table_name}.id ASC").
       limit(@reply_pages.per_page).
       offset(@reply_pages.offset).
-      all
+      to_a
 
     @reply = Message.new(:subject => "RE: #{@message.subject}")
     render :action => "show", :layout => false if request.xhr?
diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb
index 59d1d2d..9f9afcb 100644
--- a/app/controllers/my_controller.rb
+++ b/app/controllers/my_controller.rb
@@ -53,8 +53,8 @@ class MyController < ApplicationController
     @user = User.current
     @pref = @user.pref
     if request.post?
-      @user.safe_attributes = params[:user]
-      @user.pref.attributes = params[:pref]
+      @user.safe_attributes = params[:user] if params[:user]
+      @user.pref.attributes = params[:pref] if params[:pref]
       if @user.save
         @user.pref.save
         set_language_if_valid @user.language
diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb
index ffe6629..50c0489 100644
--- a/app/controllers/news_controller.rb
+++ b/app/controllers/news_controller.rb
@@ -46,7 +46,7 @@ class NewsController < ApplicationController
                       order("#{News.table_name}.created_on DESC").
                       limit(@limit).
                       offset(@offset).
-                      all
+                      to_a
     respond_to do |format|
       format.html {
         @news = News.new # for adding news inline
diff --git a/app/controllers/project_enumerations_controller.rb b/app/controllers/project_enumerations_controller.rb
index 2475dbf..df4fcbf 100644
--- a/app/controllers/project_enumerations_controller.rb
+++ b/app/controllers/project_enumerations_controller.rb
@@ -20,7 +20,7 @@ class ProjectEnumerationsController < ApplicationController
   before_filter :authorize
 
   def update
-    if request.put? && params[:enumerations]
+    if params[:enumerations]
       Project.transaction do
         params[:enumerations].each do |id, activity|
           @project.update_or_create_time_entry_activity(id, activity)
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 1225f2f..0a6b487 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -53,30 +53,30 @@ class ProjectsController < ApplicationController
         unless params[:closed]
           scope = scope.active
         end
-        @projects = scope.visible.order('lft').all
+        @projects = scope.visible.order('lft').to_a
       }
       format.api  {
         @offset, @limit = api_offset_and_limit
         @project_count = Project.visible.count
-        @projects = Project.visible.offset(@offset).limit(@limit).order('lft').all
+        @projects = Project.visible.offset(@offset).limit(@limit).order('lft').to_a
       }
       format.atom {
-        projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).all
+        projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).to_a
         render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}")
       }
     end
   end
 
   def new
-    @issue_custom_fields = IssueCustomField.sorted.all
-    @trackers = Tracker.sorted.all
+    @issue_custom_fields = IssueCustomField.sorted.to_a
+    @trackers = Tracker.sorted.to_a
     @project = Project.new
     @project.safe_attributes = params[:project]
   end
 
   def create
-    @issue_custom_fields = IssueCustomField.sorted.all
-    @trackers = Tracker.sorted.all
+    @issue_custom_fields = IssueCustomField.sorted.to_a
+    @trackers = Tracker.sorted.to_a
     @project = Project.new
     @project.safe_attributes = params[:project]
 
@@ -109,8 +109,8 @@ class ProjectsController < ApplicationController
   end
 
   def copy
-    @issue_custom_fields = IssueCustomField.sorted.all
-    @trackers = Tracker.sorted.all
+    @issue_custom_fields = IssueCustomField.sorted.to_a
+    @trackers = Tracker.sorted.to_a
     @source_project = Project.find(params[:id])
     if request.get?
       @project = Project.copy_from(@source_project)
@@ -145,8 +145,8 @@ class ProjectsController < ApplicationController
     end
 
     @users_by_role = @project.users_by_role
-    @subprojects = @project.children.visible.all
-    @news = @project.news.limit(5).includes(:author, :project).reorder("#{News.table_name}.created_on DESC").all
+    @subprojects = @project.children.visible.to_a
+    @news = @project.news.limit(5).includes(:author, :project).reorder("#{News.table_name}.created_on DESC").to_a
     @trackers = @project.rolled_up_trackers
 
     cond = @project.project_condition(Setting.display_subprojects_issues?)
@@ -167,10 +167,10 @@ class ProjectsController < ApplicationController
   end
 
   def settings
-    @issue_custom_fields = IssueCustomField.sorted.all
+    @issue_custom_fields = IssueCustomField.sorted.to_a
     @issue_category ||= IssueCategory.new
     @member ||= @project.members.new
-    @trackers = Tracker.sorted.all
+    @trackers = Tracker.sorted.to_a
     @wiki ||= @project.wiki
   end
 
diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb
index 049e353..22ec9e9 100644
--- a/app/controllers/queries_controller.rb
+++ b/app/controllers/queries_controller.rb
@@ -37,8 +37,9 @@ class QueriesController < ApplicationController
                     order("#{Query.table_name}.name").
                     limit(@limit).
                     offset(@offset).
-                    all
+                    to_a
     respond_to do |format|
+      format.html {render_error :status => 406}
       format.api
     end
   end
diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb
index 00c94a1..43dac36 100644
--- a/app/controllers/reports_controller.rb
+++ b/app/controllers/reports_controller.rb
@@ -90,6 +90,6 @@ class ReportsController < ApplicationController
   private
 
   def find_issue_statuses
-    @statuses = IssueStatus.sorted.all
+    @statuses = IssueStatus.sorted.to_a
   end
 end
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index 0ea82e5..b593217 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -69,7 +69,7 @@ class RepositoriesController < ApplicationController
       @repository.merge_extra_info(attrs[:attrs_extra])
     end
     @repository.project = @project
-    if request.put? && @repository.save
+    if @repository.save
       redirect_to settings_project_path(@project, :tab => 'repositories')
     else
       render :action => 'edit'
@@ -94,7 +94,7 @@ class RepositoriesController < ApplicationController
     @committers = @repository.committers
     @users = @project.users
     additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id)
-    @users += User.where(:id => additional_user_ids).all unless additional_user_ids.empty?
+    @users += User.where(:id => additional_user_ids).to_a unless additional_user_ids.empty?
     @users.compact!
     @users.sort!
     if request.post? && params[:committers].is_a?(Hash)
@@ -145,7 +145,7 @@ class RepositoriesController < ApplicationController
       limit(@changeset_pages.per_page).
       offset(@changeset_pages.offset).
       includes(:user, :repository, :parents).
-      all
+      to_a
 
     respond_to do |format|
       format.html { render :layout => false if request.xhr? }
@@ -411,7 +411,7 @@ class RepositoriesController < ApplicationController
     commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
     changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
 
-    # Remove email adress in usernames
+    # Remove email address in usernames
     fields = fields.collect {|c| c.gsub(%r{<.+ at .+>}, '') }
 
     graph = SVG::Graph::BarHorizontal.new(
diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb
index 8a97677..a74d8bb 100644
--- a/app/controllers/roles_controller.rb
+++ b/app/controllers/roles_controller.rb
@@ -30,7 +30,7 @@ class RolesController < ApplicationController
         render :action => "index", :layout => false if request.xhr?
       }
       format.api {
-        @roles = Role.givable.all
+        @roles = Role.givable.to_a
       }
     end
   end
@@ -47,7 +47,7 @@ class RolesController < ApplicationController
     if params[:copy].present? && @copy_from = Role.find_by_id(params[:copy])
       @role.copy_from(@copy_from)
     end
-    @roles = Role.sorted.all
+    @roles = Role.sorted.to_a
   end
 
   def create
@@ -60,7 +60,7 @@ class RolesController < ApplicationController
       flash[:notice] = l(:notice_successful_create)
       redirect_to roles_path
     else
-      @roles = Role.sorted.all
+      @roles = Role.sorted.to_a
       render :action => 'new'
     end
   end
@@ -69,7 +69,7 @@ class RolesController < ApplicationController
   end
 
   def update
-    if request.put? and @role.update_attributes(params[:role])
+    if @role.update_attributes(params[:role])
       flash[:notice] = l(:notice_successful_update)
       redirect_to roles_path
     else
@@ -86,7 +86,7 @@ class RolesController < ApplicationController
   end
 
   def permissions
-    @roles = Role.sorted.all
+    @roles = Role.sorted.to_a
     @permissions = Redmine::AccessControl.permissions.select { |p| !p.public? }
     if request.post?
       @roles.each do |role|
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index afc7566..ec8b481 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -31,7 +31,7 @@ class SearchController < ApplicationController
       when 'my_projects'
         User.current.memberships.collect(&:project)
       when 'subprojects'
-        @project ? (@project.self_and_descendants.active.all) : nil
+        @project ? (@project.self_and_descendants.active.to_a) : nil
       else
         @project
       end
diff --git a/app/controllers/sys_controller.rb b/app/controllers/sys_controller.rb
index d8ef783..0b62b42 100644
--- a/app/controllers/sys_controller.rb
+++ b/app/controllers/sys_controller.rb
@@ -19,7 +19,8 @@ class SysController < ActionController::Base
   before_filter :check_enabled
 
   def projects
-    p = Project.active.has_module(:repository).order("#{Project.table_name}.identifier").preload(:repository).all
+    p = Project.active.has_module(:repository).
+          order("#{Project.table_name}.identifier").preload(:repository).to_a
     # extra_info attribute from repository breaks activeresource client
     render :xml => p.to_xml(
                        :only => [:id, :identifier, :name, :is_public, :status],
@@ -56,7 +57,7 @@ class SysController < ActionController::Base
       raise ActiveRecord::RecordNotFound unless project
       projects << project
     else
-      projects = scope.all
+      projects = scope.to_a
     end
     projects.each do |project|
       project.repositories.each do |repository|
diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb
index e97a596..a327744 100644
--- a/app/controllers/timelog_controller.rb
+++ b/app/controllers/timelog_controller.rb
@@ -54,7 +54,7 @@ class TimelogController < ApplicationController
       format.html {
         @entry_count = scope.count
         @entry_pages = Paginator.new @entry_count, per_page_option, params['page']
-        @entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).all
+        @entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).to_a
         @total_hours = scope.sum(:hours).to_f
 
         render :layout => !request.xhr?
@@ -62,15 +62,15 @@ class TimelogController < ApplicationController
       format.api  {
         @entry_count = scope.count
         @offset, @limit = api_offset_and_limit
-        @entries = scope.offset(@offset).limit(@limit).preload(:custom_values => :custom_field).all
+        @entries = scope.offset(@offset).limit(@limit).preload(:custom_values => :custom_field).to_a
       }
       format.atom {
-        entries = scope.limit(Setting.feeds_limit.to_i).reorder("#{TimeEntry.table_name}.created_on DESC").all
+        entries = scope.limit(Setting.feeds_limit.to_i).reorder("#{TimeEntry.table_name}.created_on DESC").to_a
         render_feed(entries, :title => l(:label_spent_time))
       }
       format.csv {
         # Export all entries
-        @entries = scope.all
+        @entries = scope.to_a
         send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv')
       }
     end
@@ -232,7 +232,7 @@ private
   end
 
   def find_time_entries
-    @time_entries = TimeEntry.where(:id => params[:id] || params[:ids]).all
+    @time_entries = TimeEntry.where(:id => params[:id] || params[:ids]).to_a
     raise ActiveRecord::RecordNotFound if @time_entries.empty?
     @projects = @time_entries.collect(&:project).compact.uniq
     @project = @projects.first if @projects.size == 1
diff --git a/app/controllers/trackers_controller.rb b/app/controllers/trackers_controller.rb
index 02274d0..ec0b9ce 100644
--- a/app/controllers/trackers_controller.rb
+++ b/app/controllers/trackers_controller.rb
@@ -29,14 +29,14 @@ class TrackersController < ApplicationController
         render :action => "index", :layout => false if request.xhr?
       }
       format.api {
-        @trackers = Tracker.sorted.all
+        @trackers = Tracker.sorted.to_a
       }
     end
   end
 
   def new
     @tracker ||= Tracker.new(params[:tracker])
-    @trackers = Tracker.sorted.all
+    @trackers = Tracker.sorted.to_a
     @projects = Project.all
   end
 
@@ -95,7 +95,7 @@ class TrackersController < ApplicationController
       redirect_to fields_trackers_path
       return
     end
-    @trackers = Tracker.sorted.all
+    @trackers = Tracker.sorted.to_a
     @custom_fields = IssueCustomField.all.sort
   end
 end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index c5db589..bb56fb2 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -47,7 +47,7 @@ class UsersController < ApplicationController
     @user_count = scope.count
     @user_pages = Paginator.new @user_count, @limit, params['page']
     @offset ||= @user_pages.offset
-    @users =  scope.order(sort_clause).limit(@limit).offset(@offset).all
+    @users =  scope.order(sort_clause).limit(@limit).offset(@offset).to_a
 
     respond_to do |format|
       format.html {
@@ -60,7 +60,7 @@ class UsersController < ApplicationController
 
   def show
     # show projects based on current user visibility
-    @memberships = @user.memberships.where(Project.visible_condition(User.current)).all
+    @memberships = @user.memberships.where(Project.visible_condition(User.current)).to_a
 
     events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
     @events_by_day = events.group_by(&:event_date)
@@ -90,7 +90,7 @@ class UsersController < ApplicationController
     @user.admin = params[:user][:admin] || false
     @user.login = params[:user][:login]
     @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id
-    @user.pref.attributes = params[:pref]
+    @user.pref.attributes = params[:pref] if params[:pref]
 
     if @user.save
       Mailer.account_information(@user, @user.password).deliver if params[:send_information]
@@ -134,7 +134,7 @@ class UsersController < ApplicationController
     # Was the account actived ? (do it before User#save clears the change)
     was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE])
     # TODO: Similar to My#account
-    @user.pref.attributes = params[:pref]
+    @user.pref.attributes = params[:pref] if params[:pref]
 
     if @user.save
       @user.pref.save
diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb
index a49f8a0..bf23153 100644
--- a/app/controllers/versions_controller.rb
+++ b/app/controllers/versions_controller.rb
@@ -31,7 +31,7 @@ class VersionsController < ApplicationController
   def index
     respond_to do |format|
       format.html {
-        @trackers = @project.trackers.sorted.all
+        @trackers = @project.trackers.sorted.to_a
         retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
         @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
         project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
@@ -56,7 +56,7 @@ class VersionsController < ApplicationController
         @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
       }
       format.api {
-        @versions = @project.shared_versions.all
+        @versions = @project.shared_versions.to_a
       }
     end
   end
@@ -67,7 +67,7 @@ class VersionsController < ApplicationController
         @issues = @version.fixed_issues.visible.
           includes(:status, :tracker, :priority).
           reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
-          all
+          to_a
       }
       format.api
     end
@@ -117,7 +117,7 @@ class VersionsController < ApplicationController
   end
 
   def update
-    if request.put? && params[:version]
+    if params[:version]
       attributes = params[:version].dup
       attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
       @version.safe_attributes = attributes
diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb
index e6c4d31..ade977b 100644
--- a/app/controllers/watchers_controller.rb
+++ b/app/controllers/watchers_controller.rb
@@ -53,7 +53,7 @@ class WatchersController < ApplicationController
   def append
     if params[:watcher].is_a?(Hash)
       user_ids = params[:watcher][:user_ids] || [params[:watcher][:user_id]]
-      @users = User.active.where(:id => user_ids).all
+      @users = User.active.where(:id => user_ids).to_a
     end
     if @users.blank?
       render :nothing => true
@@ -92,7 +92,7 @@ class WatchersController < ApplicationController
   def find_watchables
     klass = Object.const_get(params[:object_type].camelcase) rescue nil
     if klass && klass.respond_to?('watched_by')
-      @watchables = klass.where(:id => Array.wrap(params[:object_id])).all
+      @watchables = klass.where(:id => Array.wrap(params[:object_id])).to_a
       raise Unauthorized if @watchables.any? {|w|
         if w.respond_to?(:visible?)
           !w.visible?
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 723c719..d6670e9 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -219,7 +219,7 @@ class WikiController < ApplicationController
       reorder('version DESC').
       limit(@version_pages.per_page + 1).
       offset(@version_pages.offset).
-      all
+      to_a
 
     render :layout => false if request.xhr?
   end
@@ -280,7 +280,7 @@ class WikiController < ApplicationController
     @pages = @wiki.pages.
                       order('title').
                       includes([:content, {:attachments => :author}]).
-                      all
+                      to_a
     respond_to do |format|
       format.html {
         export = render_to_string :action => 'export_multiple', :layout => false
@@ -360,6 +360,6 @@ private
                 reorder("#{WikiPage.table_name}.title").
                 includes(:wiki => :project).
                 includes(:parent).
-                all
+                to_a
   end
 end
diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb
index 596462c..28b0f22 100644
--- a/app/controllers/workflows_controller.rb
+++ b/app/controllers/workflows_controller.rb
@@ -18,40 +18,30 @@
 class WorkflowsController < ApplicationController
   layout 'admin'
 
-  before_filter :require_admin, :find_roles, :find_trackers
+  before_filter :require_admin
 
   def index
     @workflow_counts = WorkflowTransition.count_by_tracker_and_role
   end
 
   def edit
-    @role = Role.find_by_id(params[:role_id]) if params[:role_id]
-    @tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
+    find_trackers_roles_and_statuses_for_edit
 
-    if request.post?
-      WorkflowTransition.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
-      (params[:issue_status] || []).each { |status_id, transitions|
-        transitions.each { |new_status_id, options|
-          author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
-          assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
-          WorkflowTransition.create(:role_id => @role.id, :tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
-        }
-      }
-      if @role.save
-        flash[:notice] = l(:notice_successful_update)
-        redirect_to workflows_edit_path(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
-        return
+    if request.post? && @roles && @trackers && params[:transitions]
+      transitions = params[:transitions].deep_dup
+      transitions.each do |old_status_id, transitions_by_new_status|
+        transitions_by_new_status.each do |new_status_id, transition_by_rule|
+          transition_by_rule.reject! {|rule, transition| transition == 'no_change'}
+        end
       end
+      WorkflowTransition.replace_transitions(@trackers, @roles, transitions)
+      flash[:notice] = l(:notice_successful_update)
+      redirect_to_referer_or workflows_edit_path
+      return
     end
 
-    @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
-    if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
-      @statuses = @tracker.issue_statuses
-    end
-    @statuses ||= IssueStatus.sorted.all
-
-    if @tracker && @role && @statuses.any?
-      workflows = WorkflowTransition.where(:role_id => @role.id, :tracker_id => @tracker.id).all
+    if @trackers && @roles && @statuses.any?
+      workflows = WorkflowTransition.where(:role_id => @roles.map(&:id), :tracker_id => @trackers.map(&:id))
       @workflows = {}
       @workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
       @workflows['author'] = workflows.select {|w| w.author}
@@ -60,36 +50,31 @@ class WorkflowsController < ApplicationController
   end
 
   def permissions
-    @role = Role.find_by_id(params[:role_id]) if params[:role_id]
-    @tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
+    find_trackers_roles_and_statuses_for_edit
 
-    if request.post? && @role && @tracker
-      WorkflowPermission.replace_permissions(@tracker, @role, params[:permissions] || {})
+    if request.post? && @roles && @trackers && params[:permissions]
+      permissions = params[:permissions].deep_dup
+      permissions.each { |field, rule_by_status_id|
+        rule_by_status_id.reject! {|status_id, rule| rule == 'no_change'}
+      }
+      WorkflowPermission.replace_permissions(@trackers, @roles, permissions)
       flash[:notice] = l(:notice_successful_update)
-      redirect_to workflows_permissions_path(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
+      redirect_to_referer_or workflows_permissions_path
       return
     end
 
-    @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
-    if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
-      @statuses = @tracker.issue_statuses
-    end
-    @statuses ||= IssueStatus.sorted.all
-
-    if @role && @tracker
-      @fields = (Tracker::CORE_FIELDS_ALL - @tracker.disabled_core_fields).map {|field| [field, l("field_"+field.sub(/_id$/, ''))]}
-      @custom_fields = @tracker.custom_fields
-      @permissions = WorkflowPermission.
-          where(:tracker_id => @tracker.id, :role_id => @role.id).inject({}) do |h, w|
-        h[w.old_status_id] ||= {}
-        h[w.old_status_id][w.field_name] = w.rule
-        h
-      end
+    if @roles && @trackers
+      @fields = (Tracker::CORE_FIELDS_ALL - @trackers.map(&:disabled_core_fields).reduce(:&)).map {|field| [field, l("field_"+field.sub(/_id$/, ''))]}
+      @custom_fields = @trackers.map(&:custom_fields).flatten.uniq.sort
+      @permissions = WorkflowPermission.rules_by_status_id(@trackers, @roles)
       @statuses.each {|status| @permissions[status.id] ||= {}}
     end
   end
 
   def copy
+    @roles = Role.sorted
+    @trackers = Tracker.sorted
+
     if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any'
       @source_tracker = nil
     else
@@ -101,9 +86,9 @@ class WorkflowsController < ApplicationController
       @source_role = Role.find_by_id(params[:source_role_id].to_i)
     end
     @target_trackers = params[:target_tracker_ids].blank? ?
-        nil : Tracker.where(:id => params[:target_tracker_ids]).all
+        nil : Tracker.where(:id => params[:target_tracker_ids]).to_a
     @target_roles = params[:target_role_ids].blank? ?
-        nil : Role.where(:id => params[:target_role_ids]).all
+        nil : Role.where(:id => params[:target_role_ids]).to_a
     if request.post?
       if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
         flash.now[:error] = l(:error_workflow_copy_source)
@@ -119,11 +104,37 @@ class WorkflowsController < ApplicationController
 
   private
 
+  def find_trackers_roles_and_statuses_for_edit
+    find_roles
+    find_trackers
+    find_statuses
+  end
+
   def find_roles
-    @roles = Role.sorted.all
+    ids = Array.wrap(params[:role_id])
+    if ids == ['all']
+      @roles = Role.sorted.to_a
+    elsif ids.present?
+      @roles = Role.where(:id => ids).to_a
+    end
+    @roles = nil if @roles.blank?
   end
 
   def find_trackers
-    @trackers = Tracker.sorted.all
+    ids = Array.wrap(params[:tracker_id])
+    if ids == ['all']
+      @trackers = Tracker.sorted.to_a
+    elsif ids.present?
+      @trackers = Tracker.where(:id => ids).to_a
+    end
+    @trackers = nil if @trackers.blank?
+  end
+
+  def find_statuses
+    @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
+    if @trackers && @used_statuses_only
+      @statuses = @trackers.map(&:issue_statuses).flatten.uniq.sort.presence
+    end
+    @statuses ||= IssueStatus.sorted.to_a
   end
 end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 9932686..0106e21 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -138,9 +138,7 @@ module ApplicationHelper
     if project.archived?
       h(project.name)
     elsif options.key?(:action)
-      ActiveSupport::Deprecation.warn "#link_to_project with :action option is deprecated and will be removed in Redmine 3.0."
-      url = {:controller => 'projects', :action => 'show', :id => project}.merge(options)
-      link_to project.name, url, html_options
+      raise "#link_to_project no longer accepts :action option in Redmine 3.0"
     else
       link_to project.name, project_path(project, options), html_options
     end
@@ -158,7 +156,10 @@ module ApplicationHelper
   end
 
   # Helper that formats object for html or text rendering
-  def format_object(object, html=true)
+  def format_object(object, html=true, &block)
+    if block_given?
+      object = yield object
+    end
     case object.class.name
     when 'Array'
       object.map {|o| format_object(o, html)}.join(', ').html_safe
@@ -188,7 +189,7 @@ module ApplicationHelper
         if f.nil? || f.is_a?(String)
           f
         else
-          format_object(f, html)
+          format_object(f, html, &block)
         end
       else
         object.value.to_s
@@ -489,7 +490,7 @@ module ApplicationHelper
       h(Setting.app_title)
     else
       b = []
-      ancestors = (@project.root? ? [] : @project.ancestors.visible.all)
+      ancestors = (@project.root? ? [] : @project.ancestors.visible.to_a)
       if ancestors.any?
         root = ancestors.shift
         b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
@@ -1204,7 +1205,7 @@ module ApplicationHelper
         source
       end
     end
-    super sources, options
+    super *sources, options
   end
 
   # Overrides Rails' image_tag with themes and plugins support.
@@ -1237,7 +1238,7 @@ module ApplicationHelper
         end
       end
     end
-    super sources, options
+    super *sources, options
   end
 
   # TODO: remove this in 2.5.0
@@ -1275,17 +1276,12 @@ module ApplicationHelper
   end
 
   def sanitize_anchor_name(anchor)
-    if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java'
-      anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
-    else
-      # TODO: remove when ruby1.8 is no longer supported
-      anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
-    end
+    anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
   end
 
   # Returns the javascript tags that are included in the html layout head
   def javascript_heads
-    tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'application')
+    tags = javascript_include_tag('jquery-1.11.1-ui-1.11.0-ujs-3.1.1', 'application')
     unless User.current.pref.warn_on_leaving_unsaved == '0'
       tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });")
     end
@@ -1329,7 +1325,7 @@ module ApplicationHelper
   def api_meta(options)
     if params[:nometa].present? || request.headers['X-Redmine-Nometa']
       # compatibility mode for activeresource clients that raise
-      # an error when unserializing an array with attributes
+      # an error when deserializing an array with attributes
       nil
     else
       options
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 5629aea..66df02e 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -29,7 +29,7 @@ module GroupsHelper
     scope = User.active.sorted.not_in_group(group).like(params[:q])
     principal_count = scope.count
     principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page']
-    principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
+    principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).to_a
 
     s = content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'principals')
 
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 8d7f964..9760a8e 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -63,7 +63,7 @@ module IssuesHelper
 
   def render_issue_subject_with_tree(issue)
     s = ''
-    ancestors = issue.root? ? [] : issue.ancestors.visible.all
+    ancestors = issue.root? ? [] : issue.ancestors.visible.to_a
     ancestors.each do |ancestor|
       s << '<div>' + content_tag('p', link_to_issue(ancestor, :project => (issue.project_id != ancestor.project_id)))
     end
@@ -204,7 +204,7 @@ module IssuesHelper
         order("#{Query.table_name}.name ASC").
         # Project specific queries and global queries
         where(@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id]).
-        all
+        to_a
     end
     @sidebar_queries
   end
@@ -408,7 +408,7 @@ module IssuesHelper
     if association
       record = association.class_name.constantize.find_by_id(id)
       if record
-        record.name.force_encoding('UTF-8') if record.name.respond_to?(:force_encoding)
+        record.name.force_encoding('UTF-8')
         return record.name
       end
     end
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index 5e98643..4aae464 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -22,7 +22,7 @@ module MembersHelper
     scope = Principal.active.sorted.not_member_of(project).like(params[:q])
     principal_count = scope.count
     principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page']
-    principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
+    principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).to_a
 
     s = content_tag('div', principals_check_box_tags('membership[user_ids][]', principals), :id => 'principals')
 
diff --git a/app/helpers/my_helper.rb b/app/helpers/my_helper.rb
index 8e78dfb..5917f26 100644
--- a/app/helpers/my_helper.rb
+++ b/app/helpers/my_helper.rb
@@ -23,11 +23,12 @@ module MyHelper
       where(:project_id => User.current.projects.map(&:id)).
       where("(start_date>=? and start_date<=?) or (due_date>=? and due_date<=?)", startdt, enddt, startdt, enddt).
       includes(:project, :tracker, :priority, :assigned_to).
-      all
+      references(:project, :tracker, :priority, :assigned_to).
+      to_a
   end
 
   def documents_items
-    Document.visible.order("#{Document.table_name}.created_on DESC").limit(10).all
+    Document.visible.order("#{Document.table_name}.created_on DESC").limit(10).to_a
   end
 
   def issuesassignedtome_items
@@ -35,8 +36,9 @@ module MyHelper
       where(:assigned_to_id => ([User.current.id] + User.current.group_ids)).
       limit(10).
       includes(:status, :project, :tracker, :priority).
+      references(:status, :project, :tracker, :priority).
       order("#{IssuePriority.table_name}.position DESC, #{Issue.table_name}.updated_on DESC").
-      all
+      to_a
   end
 
   def issuesreportedbyme_items
@@ -44,12 +46,13 @@ module MyHelper
       where(:author_id => User.current.id).
       limit(10).
       includes(:status, :project, :tracker).
+      references(:status, :project, :tracker).
       order("#{Issue.table_name}.updated_on DESC").
-      all
+      to_a
   end
 
   def issueswatched_items
-    Issue.visible.on_active_project.watched_by(User.current.id).recently_updated.limit(10).all
+    Issue.visible.on_active_project.watched_by(User.current.id).recently_updated.limit(10).to_a
   end
 
   def news_items
@@ -57,15 +60,17 @@ module MyHelper
       where(:project_id => User.current.projects.map(&:id)).
       limit(10).
       includes(:project, :author).
+      references(:project, :author).
       order("#{News.table_name}.created_on DESC").
-      all
+      to_a
   end
 
   def timelog_items
     TimeEntry.
       where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", User.current.id, Date.today - 6, Date.today).
-      includes(:activity, :project, {:issue => [:tracker, :status]}).
+      joins(:activity, :project, {:issue => [:tracker, :status]}).
+      references(:activity, :project, {:issue => [:tracker, :status]}).
       order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC").
-      all
+      to_a
   end
 end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 06ec16c..d9315b9 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -20,7 +20,7 @@
 module ProjectsHelper
   def link_to_version(version, options = {})
     return '' unless version && version.is_a?(Version)
-    link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options
+    link_to_if version.visible?, format_version_name(version), version_path(version), options
   end
 
   def project_settings_tabs
@@ -53,10 +53,16 @@ module ProjectsHelper
 
   def render_project_action_links
     links = []
-    links << link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') if User.current.allowed_to?(:add_project, nil, :global => true)
-    links << link_to(l(:label_issue_view_all), issues_path) if User.current.allowed_to?(:view_issues, nil, :global => true)
-    links << link_to(l(:label_overall_spent_time), time_entries_path) if User.current.allowed_to?(:view_time_entries, nil, :global => true)
-    links << link_to(l(:label_overall_activity), { :controller => 'activities', :action => 'index', :id => nil })
+    if User.current.allowed_to?(:add_project, nil, :global => true)
+      links << link_to(l(:label_project_new), new_project_path, :class => 'icon icon-add')
+    end
+    if User.current.allowed_to?(:view_issues, nil, :global => true)
+      links << link_to(l(:label_issue_view_all), issues_path)
+    end
+    if User.current.allowed_to?(:view_time_entries, nil, :global => true)
+      links << link_to(l(:label_overall_spent_time), time_entries_path)
+    end
+    links << link_to(l(:label_overall_activity), activity_path)
     links.join(" | ").html_safe
   end
 
diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb
index 9324a9d..0206b16 100644
--- a/app/helpers/queries_helper.rb
+++ b/app/helpers/queries_helper.rb
@@ -18,6 +18,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 module QueriesHelper
+  include ApplicationHelper
+
   def filters_options_for_select(query)
     options_for_select(filters_options(query))
   end
@@ -81,7 +83,7 @@ module QueriesHelper
   end
 
   def column_content(column, issue)
-    value = column.value(issue)
+    value = column.value_object(issue)
     if value.is_a?(Array)
       value.collect {|v| column_value(column, issue, v)}.compact.join(', ').html_safe
     else
@@ -110,7 +112,7 @@ module QueriesHelper
   end
 
   def csv_content(column, issue)
-    value = column.value(issue)
+    value = column.value_object(issue)
     if value.is_a?(Array)
       value.collect {|v| csv_value(column, issue, v)}.compact.join(', ')
     else
@@ -119,22 +121,16 @@ module QueriesHelper
   end
 
   def csv_value(column, issue, value)
-    case value.class.name
-    when 'Time'
-      format_time(value)
-    when 'Date'
-      format_date(value)
-    when 'Float'
-      sprintf("%.2f", value).gsub('.', l(:general_csv_decimal_separator))
-    when 'IssueRelation'
-      other = value.other_issue(issue)
-      l(value.label_for(issue)) + " ##{other.id}"
-    when 'TrueClass'
-      l(:general_text_Yes)
-    when 'FalseClass'
-      l(:general_text_No)
-    else
-      value.to_s
+    format_object(value, false) do |value|
+      case value.class.name
+      when 'Float'
+        sprintf("%.2f", value).gsub('.', l(:general_csv_decimal_separator))
+      when 'IssueRelation'
+        other = value.other_issue(issue)
+        l(value.label_for(issue)) + " ##{other.id}"
+      else
+        value
+      end
     end
   end
 
@@ -147,7 +143,7 @@ module QueriesHelper
       end
     end
 
-    export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
+    export = CSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
       # csv header fields
       csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(c.caption.to_s, encoding) }
       # csv lines
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index 17606a3..3e672b9 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -84,12 +84,24 @@ module SettingsHelper
 
   # Renders a notification field for a Redmine::Notifiable option
   def notification_field(notifiable)
-    return content_tag(:label,
-                       check_box_tag('settings[notified_events][]',
-                                     notifiable.name,
-                                     Setting.notified_events.include?(notifiable.name), :id => nil).html_safe +
-                         l_or_humanize(notifiable.name, :prefix => 'label_').html_safe,
-                       :class => notifiable.parent.present? ? "parent" : '').html_safe
+    tag_data = notifiable.parent.present? ?
+      {:parent_notifiable => notifiable.parent} :
+      {:disables => "input[data-parent-notifiable=#{notifiable.name}]"}
+
+    tag = check_box_tag('settings[notified_events][]',
+      notifiable.name,
+      Setting.notified_events.include?(notifiable.name),
+      :id => nil,
+      :data => tag_data)
+
+    text = l_or_humanize(notifiable.name, :prefix => 'label_')
+
+    options = {}
+    if notifiable.parent.present?
+      options[:class] = "parent"
+    end
+
+    content_tag(:label, tag + text, options)
   end
 
   def cross_project_subtasks_options
diff --git a/app/helpers/sort_helper.rb b/app/helpers/sort_helper.rb
index 13beed3..c1c1d86 100644
--- a/app/helpers/sort_helper.rb
+++ b/app/helpers/sort_helper.rb
@@ -84,7 +84,8 @@ module SortHelper
     def to_sql
       sql = @criteria.collect do |k,o|
         if s = @available_criteria[k]
-          (o ? s.to_a : s.to_a.collect {|c| append_desc(c)})
+          s = [s] unless s.is_a?(Array)
+          (o ? s : s.collect {|c| append_desc(c)})
         end
       end.flatten.compact
       sql.blank? ? nil : sql
diff --git a/app/helpers/timelog_helper.rb b/app/helpers/timelog_helper.rb
index 02532c3..c68d2c0 100644
--- a/app/helpers/timelog_helper.rb
+++ b/app/helpers/timelog_helper.rb
@@ -105,7 +105,7 @@ module TimelogHelper
 
   def report_to_csv(report)
     decimal_separator = l(:general_csv_decimal_separator)
-    export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
+    export = CSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
       # Column headers
       headers = report.criteria.collect {|criteria| l(report.available_criteria[criteria][:label]) }
       headers += report.periods
diff --git a/app/helpers/workflows_helper.rb b/app/helpers/workflows_helper.rb
index bfeacd8..28f4fc2 100644
--- a/app/helpers/workflows_helper.rb
+++ b/app/helpers/workflows_helper.rb
@@ -18,24 +18,78 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 module WorkflowsHelper
+  def options_for_workflow_select(name, objects, selected, options={})
+    option_tags = ''.html_safe
+    multiple = false
+    if selected 
+      if selected.size == objects.size
+        selected = 'all'
+      else
+        selected = selected.map(&:id)
+        if selected.size > 1
+          multiple = true
+        end
+      end
+    else
+      selected = objects.first.try(:id)
+    end
+    all_tag_options = {:value => 'all', :selected => (selected == 'all')}
+    if multiple
+      all_tag_options.merge!(:style => "display:none;")
+    end
+    option_tags << content_tag('option', l(:label_all), all_tag_options)
+    option_tags << options_from_collection_for_select(objects, "id", "name", selected)
+    select_tag name, option_tags, {:multiple => multiple}.merge(options)
+  end
+
   def field_required?(field)
     field.is_a?(CustomField) ? field.is_required? : %w(project_id tracker_id subject priority_id is_private).include?(field)
   end
 
-  def field_permission_tag(permissions, status, field, role)
+  def field_permission_tag(permissions, status, field, roles)
     name = field.is_a?(CustomField) ? field.id.to_s : field
     options = [["", ""], [l(:label_readonly), "readonly"]]
     options << [l(:label_required), "required"] unless field_required?(field)
     html_options = {}
-    selected = permissions[status.id][name]
+    
+    if perm = permissions[status.id][name]
+      if perm.uniq.size > 1 || perm.size < @roles.size * @trackers.size
+        options << [l(:label_no_change_option), "no_change"]
+        selected = 'no_change'
+      else
+        selected = perm.first
+      end
+    end
+
+    hidden = field.is_a?(CustomField) &&
+      !field.visible? &&
+      !roles.detect {|role| role.custom_fields.to_a.include?(field)}
 
-    hidden = field.is_a?(CustomField) && !field.visible? && !role.custom_fields.to_a.include?(field)
     if hidden
       options[0][0] = l(:label_hidden)
       selected = ''
       html_options[:disabled] = true
     end
 
-    select_tag("permissions[#{name}][#{status.id}]", options_for_select(options, selected), html_options)
+    select_tag("permissions[#{status.id}][#{name}]", options_for_select(options, selected), html_options)
+  end
+
+  def transition_tag(workflows, old_status, new_status, name)
+    w = workflows.select {|w| w.old_status_id == old_status.id && w.new_status_id == new_status.id}.size
+    
+    tag_name = "transitions[#{ old_status.id }][#{new_status.id}][#{name}]"
+    if w == 0 || w == @roles.size * @trackers.size
+      
+      hidden_field_tag(tag_name, "0") +
+      check_box_tag(tag_name, "1", w != 0,
+            :class => "old-status-#{old_status.id} new-status-#{new_status.id}")
+    else
+      select_tag tag_name,
+        options_for_select([
+            [l(:general_text_Yes), "1"],
+            [l(:general_text_No), "0"],
+            [l(:label_no_change_option), "no_change"]
+          ], "no_change")
+    end
   end
 end
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index f36f7cc..9d7e032 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -27,6 +27,7 @@ class Attachment < ActiveRecord::Base
   validates_length_of :disk_filename, :maximum => 255
   validates_length_of :description, :maximum => 255
   validate :validate_max_file_size
+  attr_protected :id
 
   acts_as_event :title => :filename,
                 :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id, :filename => o.filename}}
@@ -34,16 +35,16 @@ class Attachment < ActiveRecord::Base
   acts_as_activity_provider :type => 'files',
                             :permission => :view_files,
                             :author_key => :author_id,
-                            :find_options => {:select => "#{Attachment.table_name}.*",
-                                              :joins => "LEFT JOIN #{Version.table_name} ON #{Attachment.table_name}.container_type='Version' AND #{Version.table_name}.id = #{Attachment.table_name}.container_id " +
-                                                        "LEFT JOIN #{Project.table_name} ON #{Version.table_name}.project_id = #{Project.table_name}.id OR ( #{Attachment.table_name}.container_type='Project' AND #{Attachment.table_name}.container_id = #{Project.table_name}.id )"}
+                            :scope => select("#{Attachment.table_name}.*").
+                                      joins("LEFT JOIN #{Version.table_name} ON #{Attachment.table_name}.container_type='Version' AND #{Version.table_name}.id = #{Attachment.table_name}.container_id " +
+                                            "LEFT JOIN #{Project.table_name} ON #{Version.table_name}.project_id = #{Project.table_name}.id OR ( #{Attachment.table_name}.container_type='Project' AND #{Attachment.table_name}.container_id = #{Project.table_name}.id )")
 
   acts_as_activity_provider :type => 'documents',
                             :permission => :view_documents,
                             :author_key => :author_id,
-                            :find_options => {:select => "#{Attachment.table_name}.*",
-                                              :joins => "LEFT JOIN #{Document.table_name} ON #{Attachment.table_name}.container_type='Document' AND #{Document.table_name}.id = #{Attachment.table_name}.container_id " +
-                                                        "LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id"}
+                            :scope => select("#{Attachment.table_name}.*").
+                                      joins("LEFT JOIN #{Document.table_name} ON #{Attachment.table_name}.container_type='Document' AND #{Document.table_name}.id = #{Attachment.table_name}.container_id " +
+                                            "LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id")
 
   cattr_accessor :storage_path
   @@storage_path = Redmine::Configuration['attachments_storage_path'] || File.join(Rails.root, "files")
@@ -74,7 +75,7 @@ class Attachment < ActiveRecord::Base
       if @temp_file.size > 0
         if @temp_file.respond_to?(:original_filename)
           self.filename = @temp_file.original_filename
-          self.filename.force_encoding("UTF-8") if filename.respond_to?(:force_encoding)
+          self.filename.force_encoding("UTF-8")
         end
         if @temp_file.respond_to?(:content_type)
           self.content_type = @temp_file.content_type.to_s.chomp
diff --git a/app/models/auth_source.rb b/app/models/auth_source.rb
index 1494e16..aa2506e 100644
--- a/app/models/auth_source.rb
+++ b/app/models/auth_source.rb
@@ -29,6 +29,7 @@ class AuthSource < ActiveRecord::Base
   validates_presence_of :name
   validates_uniqueness_of :name
   validates_length_of :name, :maximum => 60
+  attr_protected :id
 
   def authenticate(login, password)
   end
diff --git a/app/models/auth_source_ldap.rb b/app/models/auth_source_ldap.rb
index 4c963be..faebdea 100644
--- a/app/models/auth_source_ldap.rb
+++ b/app/models/auth_source_ldap.rb
@@ -175,20 +175,16 @@ class AuthSourceLdap < AuthSource
     end
     attrs = {}
     search_filter = base_filter & Net::LDAP::Filter.eq(self.attr_login, login)
-
     ldap_con.search( :base => self.base_dn,
                      :filter => search_filter,
                      :attributes=> search_attributes) do |entry|
-
       if onthefly_register?
         attrs = get_user_attributes_from_ldap_entry(entry)
       else
         attrs = {:dn => entry.dn}
       end
-
       logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
     end
-
     attrs
   end
 
diff --git a/app/models/board.rb b/app/models/board.rb
index 387792c..2cbeb0a 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -18,8 +18,8 @@
 class Board < ActiveRecord::Base
   include Redmine::SafeAttributes
   belongs_to :project
-  has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
-  has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC"
+  has_many :topics, lambda {where("#{Message.table_name}.parent_id IS NULL").order("#{Message.table_name}.created_on DESC")}, :class_name => 'Message'
+  has_many :messages, lambda {order("#{Message.table_name}.created_on DESC")}, :dependent => :destroy
   belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
   acts_as_tree :dependent => :nullify
   acts_as_list :scope => '(project_id = #{project_id} AND parent_id #{parent_id ? "= #{parent_id}" : "IS NULL"})'
@@ -29,9 +29,12 @@ class Board < ActiveRecord::Base
   validates_length_of :name, :maximum => 30
   validates_length_of :description, :maximum => 255
   validate :validate_board
+  attr_protected :id
 
   scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
+    joins(:project).
+    references(:project).
+    where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
   }
 
   safe_attributes 'name', 'description', 'parent_id', 'move_to'
diff --git a/app/models/change.rb b/app/models/change.rb
index 6ef56e0..b24c1bd 100644
--- a/app/models/change.rb
+++ b/app/models/change.rb
@@ -21,6 +21,7 @@ class Change < ActiveRecord::Base
   validates_presence_of :changeset_id, :action, :path
   before_save :init_path
   before_validation :replace_invalid_utf8_of_path
+  attr_protected :id
 
   def relative_path
     changeset.repository.relative_path(path)
diff --git a/app/models/changeset.rb b/app/models/changeset.rb
index fea170d..81894bb 100644
--- a/app/models/changeset.rb
+++ b/app/models/changeset.rb
@@ -35,20 +35,23 @@ class Changeset < ActiveRecord::Base
                 :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :repository_id => o.repository.identifier_param, :rev => o.identifier}}
 
   acts_as_searchable :columns => 'comments',
-                     :include => {:repository => :project},
+                     :scope => preload(:repository => :project),
                      :project_key => "#{Repository.table_name}.project_id",
                      :date_column => 'committed_on'
 
   acts_as_activity_provider :timestamp => "#{table_name}.committed_on",
                             :author_key => :user_id,
-                            :find_options => {:include => [:user, {:repository => :project}]}
+                            :scope => preload(:user, {:repository => :project})
 
   validates_presence_of :repository_id, :revision, :committed_on, :commit_date
   validates_uniqueness_of :revision, :scope => :repository_id
   validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
+  attr_protected :id
 
   scope :visible, lambda {|*args|
-    includes(:repository => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args))
+    joins(:repository => :project).
+    references(:repository => :project).
+    where(Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args))
   }
 
   after_create :scan_for_issues
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 02d9a3b..9893ad6 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -21,6 +21,7 @@ class Comment < ActiveRecord::Base
   belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
 
   validates_presence_of :commented, :author, :comments
+  attr_protected :id
 
   after_create :send_notification
 
diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb
index 48ef2c7..f3829bf 100644
--- a/app/models/custom_field.rb
+++ b/app/models/custom_field.rb
@@ -29,6 +29,7 @@ class CustomField < ActiveRecord::Base
   validates_length_of :name, :maximum => 30
   validates_inclusion_of :field_format, :in => Proc.new { Redmine::FieldFormat.available_formats }
   validate :validate_custom_field
+  attr_protected :id
 
   before_validation :set_searchable
   before_save do |field|
@@ -117,7 +118,7 @@ class CustomField < ActiveRecord::Base
     values = read_attribute(:possible_values)
     if values.is_a?(Array)
       values.each do |value|
-        value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
+        value.force_encoding('UTF-8')
       end
       values
     else
@@ -218,7 +219,7 @@ class CustomField < ActiveRecord::Base
 
   # to move in project_custom_field
   def self.for_all
-    where(:is_for_all => true).order('position').all
+    where(:is_for_all => true).order('position').to_a
   end
 
   def type_name
diff --git a/app/models/custom_value.rb b/app/models/custom_value.rb
index 9526463..ab2eee7 100644
--- a/app/models/custom_value.rb
+++ b/app/models/custom_value.rb
@@ -18,6 +18,7 @@
 class CustomValue < ActiveRecord::Base
   belongs_to :custom_field
   belongs_to :customized, :polymorphic => true
+  attr_protected :id
 
   def initialize(attributes=nil, *args)
     super
diff --git a/app/models/document.rb b/app/models/document.rb
index 4609d86..c195f64 100644
--- a/app/models/document.rb
+++ b/app/models/document.rb
@@ -21,19 +21,23 @@ class Document < ActiveRecord::Base
   belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
   acts_as_attachable :delete_permission => :delete_documents
 
-  acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
+  acts_as_searchable :columns => ['title', "#{table_name}.description"],
+                     :scope => preload(:project)
   acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
                 :author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
                 :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
-  acts_as_activity_provider :find_options => {:include => :project}
+  acts_as_activity_provider :scope => preload(:project)
 
   validates_presence_of :project, :title, :category
   validates_length_of :title, :maximum => 60
+  attr_protected :id
 
   after_create :send_notification
 
   scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
+    joins(:project).
+    references(:project).
+    where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
   }
 
   safe_attributes 'category_id', 'title', 'description'
diff --git a/app/models/enabled_module.rb b/app/models/enabled_module.rb
index 1cc84aa..baf6cdd 100644
--- a/app/models/enabled_module.rb
+++ b/app/models/enabled_module.rb
@@ -21,6 +21,7 @@ class EnabledModule < ActiveRecord::Base
 
   validates_presence_of :name
   validates_uniqueness_of :name, :scope => :project_id
+  attr_protected :id
 
   after_create :module_enabled
 
diff --git a/app/models/enumeration.rb b/app/models/enumeration.rb
index b593665..8c82a0d 100644
--- a/app/models/enumeration.rb
+++ b/app/models/enumeration.rb
@@ -18,7 +18,7 @@
 class Enumeration < ActiveRecord::Base
   include Redmine::SubclassFactory
 
-  default_scope :order => "#{Enumeration.table_name}.position ASC"
+  default_scope lambda {order("#{Enumeration.table_name}.position ASC")}
 
   belongs_to :project
 
@@ -73,7 +73,7 @@ class Enumeration < ActiveRecord::Base
     self.objects_count != 0
   end
 
-  # Is this enumeration overiding a system level enumeration?
+  # Is this enumeration overriding a system level enumeration?
   def is_override?
     !self.parent.nil?
   end
@@ -103,8 +103,14 @@ class Enumeration < ActiveRecord::Base
     subclasses
   end
 
-  # Does the +new+ Hash override the previous Enumeration?
+  # TODO: remove in Redmine 3.0
   def self.overridding_change?(new, previous)
+    ActiveSupport::Deprecation.warn "Enumeration#overridding_change? is deprecated and will be removed in Redmine 3.0. Please use #overriding_change?."
+    overriding_change?(new, previous)
+  end
+
+  # Does the +new+ Hash override the previous Enumeration?
+  def self.overriding_change?(new, previous)
     if (same_active_state?(new['active'], previous.active)) && same_custom_values?(new,previous)
       return false
     else
diff --git a/app/models/group.rb b/app/models/group.rb
index 9824bd9..d2ce6cc 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -28,6 +28,7 @@ class Group < Principal
   validates_presence_of :lastname
   validates_uniqueness_of :lastname, :case_sensitive => false
   validates_length_of :lastname, :maximum => 255
+  attr_protected :id
 
   before_destroy :remove_references_before_destroy
 
@@ -66,7 +67,8 @@ class Group < Principal
   def user_removed(user)
     members.each do |member|
       MemberRole.
-        includes(:member).
+        joins(:member).
+        references(:member).
         where("#{Member.table_name}.user_id = ? AND #{MemberRole.table_name}.inherited_from IN (?)", user.id, member.member_role_ids).
         each(&:destroy)
     end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 3ee7fc8..89fa42a 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -31,15 +31,12 @@ class Issue < ActiveRecord::Base
 
   has_many :journals, :as => :journalized, :dependent => :destroy
   has_many :visible_journals,
+    lambda {where(["(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))", false])},
     :class_name => 'Journal',
-    :as => :journalized,
-    :conditions => Proc.new { 
-      ["(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))", false]
-    },
-    :readonly => true
+    :as => :journalized
 
   has_many :time_entries, :dependent => :destroy
-  has_and_belongs_to_many :changesets, :order => "#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC"
+  has_and_belongs_to_many :changesets, lambda {order("#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC")}
 
   has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
   has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
@@ -49,14 +46,19 @@ class Issue < ActiveRecord::Base
   acts_as_customizable
   acts_as_watchable
   acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"],
-                     :include => [:project, :visible_journals],
                      # sort by id so that limited eager loading doesn't break with postgresql
-                     :order_column => "#{table_name}.id"
+                     :order_column => "#{table_name}.id",
+                     :scope => lambda { joins(:project).
+                                        joins("LEFT OUTER JOIN #{Journal.table_name} ON #{Journal.table_name}.journalized_type='Issue'" + 
+                                              " AND #{Journal.table_name}.journalized_id = #{Issue.table_name}.id" +
+                                              " AND (#{Journal.table_name}.private_notes = #{connection.quoted_false}" +
+                                                    " OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))") }
+
   acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id} (#{o.status}): #{o.subject}"},
                 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}},
                 :type => Proc.new {|o| 'issue' + (o.closed? ? ' closed' : '') }
 
-  acts_as_activity_provider :find_options => {:include => [:project, :author, :tracker]},
+  acts_as_activity_provider :scope => preload(:project, :author, :tracker),
                             :author_key => :author_id
 
   DONE_RATIO_OPTIONS = %w(issue_field issue_status)
@@ -72,19 +74,26 @@ class Issue < ActiveRecord::Base
   validates :start_date, :date => true
   validates :due_date, :date => true
   validate :validate_issue, :validate_required_fields
+  attr_protected :id
 
   scope :visible, lambda {|*args|
-    includes(:project).where(Issue.visible_condition(args.shift || User.current, *args))
+    joins(:project).
+    references(:project).
+    where(Issue.visible_condition(args.shift || User.current, *args))
   }
 
   scope :open, lambda {|*args|
     is_closed = args.size > 0 ? !args.first : false
-    includes(:status).where("#{IssueStatus.table_name}.is_closed = ?", is_closed)
+    joins(:status).
+    references(:status).
+    where("#{IssueStatus.table_name}.is_closed = ?", is_closed)
   }
 
   scope :recently_updated, lambda { order("#{Issue.table_name}.updated_on DESC") }
   scope :on_active_project, lambda {
-    includes(:status, :project, :tracker).where("#{Project.table_name}.status = ?", Project::STATUS_ACTIVE)
+    joins(:project).
+    references(:project).
+    where("#{Project.table_name}.status = ?", Project::STATUS_ACTIVE)
   }
   scope :fixed_version, lambda {|versions|
     ids = [versions].flatten.compact.map {|v| v.is_a?(Version) ? v.id : v}
@@ -94,7 +103,7 @@ class Issue < ActiveRecord::Base
   before_create :default_assign
   before_save :close_duplicates, :update_done_ratio_from_issue_status,
               :force_updated_on_change, :update_closed_on, :set_assigned_to_was
-  after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?} 
+  after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?}
   after_save :reschedule_following_issues, :update_nested_set_attributes,
              :update_parent_attributes, :create_journal
   # Should be after_create but would be called before previous after_save callbacks
@@ -218,7 +227,7 @@ class Issue < ActiveRecord::Base
     self.status = issue.status
     self.author = User.current
     unless options[:attachments] == false
-      self.attachments = issue.attachments.map do |attachement| 
+      self.attachments = issue.attachments.map do |attachement|
         attachement.copy(:container => self)
       end
     end
@@ -351,6 +360,10 @@ class Issue < ActiveRecord::Base
   # Do not redefine alias chain on reload (see #4838)
   alias_method_chain(:assign_attributes, :project_and_tracker_first) unless method_defined?(:assign_attributes_without_project_and_tracker_first)
 
+  def attributes=(new_attributes)
+    assign_attributes new_attributes
+  end
+
   def estimated_hours=(h)
     write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
   end
@@ -394,10 +407,10 @@ class Issue < ActiveRecord::Base
     :if => lambda {|issue, user| user.allowed_to?(:add_issue_notes, issue.project)}
 
   safe_attributes 'private_notes',
-    :if => lambda {|issue, user| !issue.new_record? && user.allowed_to?(:set_notes_private, issue.project)} 
+    :if => lambda {|issue, user| !issue.new_record? && user.allowed_to?(:set_notes_private, issue.project)}
 
   safe_attributes 'watcher_user_ids',
-    :if => lambda {|issue, user| issue.new_record? && user.allowed_to?(:add_issue_watchers, issue.project)} 
+    :if => lambda {|issue, user| issue.new_record? && user.allowed_to?(:add_issue_watchers, issue.project)}
 
   safe_attributes 'is_private',
     :if => lambda {|issue, user|
@@ -423,7 +436,7 @@ class Issue < ActiveRecord::Base
   def safe_attributes=(attrs, user=User.current)
     return unless attrs.is_a?(Hash)
 
-    attrs = attrs.dup
+    attrs = attrs.deep_dup
 
     # Project and Tracker must be set before since new_statuses_allowed_to depends on it.
     if (p = attrs.delete('project_id')) && safe_attribute?('project_id')
@@ -458,14 +471,12 @@ class Issue < ActiveRecord::Base
 
     if attrs['custom_field_values'].present?
       editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s}
-      # TODO: use #select when ruby1.8 support is dropped
-      attrs['custom_field_values'] = attrs['custom_field_values'].reject {|k, v| !editable_custom_field_ids.include?(k.to_s)}
+      attrs['custom_field_values'].select! {|k, v| editable_custom_field_ids.include?(k.to_s)}
     end
 
     if attrs['custom_fields'].present?
       editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s}
-      # TODO: use #select when ruby1.8 support is dropped
-      attrs['custom_fields'] = attrs['custom_fields'].reject {|c| !editable_custom_field_ids.include?(c['id'].to_s)}
+      attrs['custom_fields'].select! {|c| editable_custom_field_ids.include?(c['id'].to_s)}
     end
 
     # mass-assignment security bypass
@@ -529,7 +540,7 @@ class Issue < ActiveRecord::Base
     return {} if roles.empty?
 
     result = {}
-    workflow_permissions = WorkflowPermission.where(:tracker_id => tracker_id, :old_status_id => status_id, :role_id => roles.map(&:id)).all
+    workflow_permissions = WorkflowPermission.where(:tracker_id => tracker_id, :old_status_id => status_id, :role_id => roles.map(&:id))
     if workflow_permissions.any?
       workflow_rules = workflow_permissions.inject({}) do |h, wp|
         h[wp.field_name] ||= []
@@ -733,7 +744,7 @@ class Issue < ActiveRecord::Base
   def assignable_versions
     return @assignable_versions if @assignable_versions
 
-    versions = project.shared_versions.open.all
+    versions = project.shared_versions.open.to_a
     if fixed_version
       if fixed_version_id_changed?
         # nothing to do
@@ -767,7 +778,7 @@ class Issue < ActiveRecord::Base
       initial_status ||= status
 
       initial_assigned_to_id = assigned_to_id_changed? ? assigned_to_id_was : assigned_to_id
-      assignee_transitions_allowed = initial_assigned_to_id.present? && 
+      assignee_transitions_allowed = initial_assigned_to_id.present? &&
         (user.id == initial_assigned_to_id || user.group_ids.include?(initial_assigned_to_id))
 
       statuses = initial_status.find_new_statuses_allowed_to(
@@ -879,10 +890,14 @@ class Issue < ActiveRecord::Base
     if issues.any?
       issue_ids = issues.map(&:id)
       # Relations with issue_from in given issues and visible issue_to
-      relations_from = IssueRelation.includes(:issue_to => [:status, :project]).where(visible_condition(user)).where(:issue_from_id => issue_ids).all
+      relations_from = IssueRelation.joins(:issue_to => :project).
+                         references(:issue_to => :project).
+                         where(visible_condition(user)).where(:issue_from_id => issue_ids).to_a
       # Relations with issue_to in given issues and visible issue_from
-      relations_to = IssueRelation.includes(:issue_from => [:status, :project]).where(visible_condition(user)).where(:issue_to_id => issue_ids).all
-
+      relations_to = IssueRelation.joins(:issue_from => :project).
+                         references(:issue_from => :project).
+                         where(visible_condition(user)).
+                         where(:issue_to_id => issue_ids).to_a
       issues.each do |issue|
         relations =
           relations_from.select {|relation| relation.issue_from_id == issue.id} +
@@ -1061,7 +1076,7 @@ class Issue < ActiveRecord::Base
         if leaf.start_date
           # Only move subtask if it starts at the same date as the parent
           # or if it starts before the given date
-          if start_date == leaf.start_date || date > leaf.start_date 
+          if start_date == leaf.start_date || date > leaf.start_date
             leaf.reschedule_on!(date)
           end
         else
@@ -1112,7 +1127,10 @@ class Issue < ActiveRecord::Base
   def self.update_versions_from_hierarchy_change(project)
     moved_project_ids = project.self_and_descendants.reload.collect(&:id)
     # Update issues of the moved projects and issues assigned to a version of a moved project
-    Issue.update_versions(["#{Version.table_name}.project_id IN (?) OR #{Issue.table_name}.project_id IN (?)", moved_project_ids, moved_project_ids])
+    Issue.update_versions(
+            ["#{Version.table_name}.project_id IN (?) OR #{Issue.table_name}.project_id IN (?)",
+             moved_project_ids, moved_project_ids]
+          )
   end
 
   def parent_issue_id=(arg)
@@ -1196,13 +1214,13 @@ class Issue < ActiveRecord::Base
   end
 
   def self.by_subproject(project)
-    ActiveRecord::Base.connection.select_all("select    s.id as status_id, 
-                                                s.is_closed as closed, 
+    ActiveRecord::Base.connection.select_all("select    s.id as status_id,
+                                                s.is_closed as closed,
                                                 #{Issue.table_name}.project_id as project_id,
-                                                count(#{Issue.table_name}.id) as total 
-                                              from 
+                                                count(#{Issue.table_name}.id) as total
+                                              from
                                                 #{Issue.table_name}, #{Project.table_name}, #{IssueStatus.table_name} s
-                                              where 
+                                              where
                                                 #{Issue.table_name}.status_id=s.id
                                                 and #{Issue.table_name}.project_id = #{Project.table_name}.id
                                                 and #{visible_condition(User.current, :project => project, :with_subprojects => true)}
@@ -1292,9 +1310,7 @@ class Issue < ActiveRecord::Base
     if root_id.nil?
       # issue was just created
       self.root_id = (@parent_issue.nil? ? id : @parent_issue.root_id)
-      set_default_left_and_right
-      Issue.where(["id = ?", id]).
-        update_all(["root_id = ?, lft = ?, rgt = ?", root_id, lft, rgt])
+      Issue.where(["id = ?", id]).update_all(["root_id = ?", root_id])
       if @parent_issue
         move_to_child_of(@parent_issue)
       end
@@ -1317,13 +1333,18 @@ class Issue < ActiveRecord::Base
         move_to_right_of(root)
       end
       old_root_id = root_id
-      self.root_id = (@parent_issue.nil? ? id : @parent_issue.root_id )
-      target_maxright = nested_set_scope.maximum(right_column_name) || 0
-      offset = target_maxright + 1 - lft
-      Issue.where(["root_id = ? AND lft >= ? AND rgt <= ? ", old_root_id, lft, rgt]).
-        update_all(["root_id = ?, lft = lft + ?, rgt = rgt + ?", root_id, offset, offset])
-      self[left_column_name] = lft + offset
-      self[right_column_name] = rgt + offset
+      in_tenacious_transaction do
+        @parent_issue.reload_nested_set if @parent_issue
+        self.reload_nested_set
+        self.root_id = (@parent_issue.nil? ? id : @parent_issue.root_id)
+        cond = ["root_id = ? AND lft >= ? AND rgt <= ? ", old_root_id, lft, rgt]
+        self.class.base_class.select('id').lock(true).where(cond)
+        offset = rdm_right_most_bound + 1 - lft
+        Issue.where(cond).
+          update_all(["root_id = ?, lft = lft + ?, rgt = rgt + ?", root_id, offset, offset])
+        self[left_column_name]  = lft + offset
+        self[right_column_name] = rgt + offset
+      end
       if @parent_issue
         move_to_child_of(@parent_issue)
       end
@@ -1338,6 +1359,14 @@ class Issue < ActiveRecord::Base
     recalculate_attributes_for(former_parent_id) if former_parent_id
   end
 
+  def rdm_right_most_bound
+    right_most_node =
+      self.class.base_class.unscoped.
+        order("#{quoted_right_column_full_name} desc").limit(1).lock(true).first
+      right_most_node ? (right_most_node[right_column_name] || 0 ) : 0
+  end
+  private :rdm_right_most_bound
+
   def update_parent_attributes
     recalculate_attributes_for(parent_id) if parent_id
   end
@@ -1366,7 +1395,7 @@ class Issue < ActiveRecord::Base
           end
           done = p.leaves.joins(:status).
             sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
-                "* (CASE WHEN is_closed = #{connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f
+                "* (CASE WHEN is_closed = #{self.class.connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f
           progress = done / (average * leaves_count)
           p.done_ratio = progress.round
         end
@@ -1386,7 +1415,8 @@ class Issue < ActiveRecord::Base
   def self.update_versions(conditions=nil)
     # Only need to update issues with a fixed_version from
     # a different project and that is not systemwide shared
-    Issue.includes(:project, :fixed_version).
+    Issue.joins(:project, :fixed_version).
+      references(:version, :fixed_version).
       where("#{Issue.table_name}.fixed_version_id IS NOT NULL" +
         " AND #{Issue.table_name}.project_id <> #{Version.table_name}.project_id" +
         " AND #{Version.table_name}.sharing <> 'system'").
@@ -1435,7 +1465,7 @@ class Issue < ActiveRecord::Base
   def close_duplicates
     if closing?
       duplicates.each do |duplicate|
-        # Reload is need in case the duplicate was updated by a previous duplicate
+        # Reload is needed in case the duplicate was updated by a previous duplicate
         duplicate.reload
         # Don't re-close it if it's already closed
         next if duplicate.closed?
@@ -1490,11 +1520,11 @@ class Issue < ActiveRecord::Base
           before = @custom_values_before_change[c.custom_field_id]
           after = c.value
           next if before == after || (before.blank? && after.blank?)
-          
+
           if before.is_a?(Array) || after.is_a?(Array)
             before = [before] unless before.is_a?(Array)
             after = [after] unless after.is_a?(Array)
-            
+
             # values removed
             (before - after).reject(&:blank?).each do |value|
               @current_journal.details << JournalDetail.new(:property => 'cf',
@@ -1555,14 +1585,14 @@ class Issue < ActiveRecord::Base
 
     where = "#{Issue.table_name}.#{select_field}=j.id"
 
-    ActiveRecord::Base.connection.select_all("select    s.id as status_id, 
-                                                s.is_closed as closed, 
+    ActiveRecord::Base.connection.select_all("select    s.id as status_id,
+                                                s.is_closed as closed,
                                                 j.id as #{select_field},
-                                                count(#{Issue.table_name}.id) as total 
-                                              from 
+                                                count(#{Issue.table_name}.id) as total
+                                              from
                                                   #{Issue.table_name}, #{Project.table_name}, #{IssueStatus.table_name} s, #{joins} j
-                                              where 
-                                                #{Issue.table_name}.status_id=s.id 
+                                              where
+                                                #{Issue.table_name}.status_id=s.id
                                                 and #{where}
                                                 and #{Issue.table_name}.project_id=#{Project.table_name}.id
                                                 and #{visible_condition(User.current, :project => project)}
diff --git a/app/models/issue_category.rb b/app/models/issue_category.rb
index 7bee6f2..e5e5088 100644
--- a/app/models/issue_category.rb
+++ b/app/models/issue_category.rb
@@ -24,6 +24,7 @@ class IssueCategory < ActiveRecord::Base
   validates_presence_of :name
   validates_uniqueness_of :name, :scope => [:project_id]
   validates_length_of :name, :maximum => 30
+  attr_protected :id
 
   safe_attributes 'name', 'assigned_to_id'
 
diff --git a/app/models/issue_custom_field.rb b/app/models/issue_custom_field.rb
index 16cb83e..ce26437 100644
--- a/app/models/issue_custom_field.rb
+++ b/app/models/issue_custom_field.rb
@@ -32,7 +32,7 @@ class IssueCustomField < CustomField
     sql = super
     id_column ||= id
     tracker_condition = "#{Issue.table_name}.tracker_id IN (SELECT tracker_id FROM #{table_name_prefix}custom_fields_trackers#{table_name_suffix} WHERE custom_field_id = #{id_column})"
-    project_condition = "EXISTS (SELECT 1 FROM #{CustomField.table_name} ifa WHERE ifa.is_for_all = #{connection.quoted_true} AND ifa.id = #{id_column})" + 
+    project_condition = "EXISTS (SELECT 1 FROM #{CustomField.table_name} ifa WHERE ifa.is_for_all = #{self.class.connection.quoted_true} AND ifa.id = #{id_column})" + 
       " OR #{Issue.table_name}.project_id IN (SELECT project_id FROM #{table_name_prefix}custom_fields_projects#{table_name_suffix} WHERE custom_field_id = #{id_column})"
 
     "((#{sql}) AND (#{tracker_condition}) AND (#{project_condition}))"
diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb
index bf90f56..b7091cb 100644
--- a/app/models/issue_query.rb
+++ b/app/models/issue_query.rb
@@ -45,7 +45,9 @@ class IssueQuery < Query
   scope :visible, lambda {|*args|
     user = args.shift || User.current
     base = Project.allowed_to_condition(user, :view_issues, *args)
-    scope = includes(:project).where("#{table_name}.project_id IS NULL OR (#{base})")
+    scope = joins("LEFT OUTER JOIN #{Project.table_name} ON #{table_name}.project_id = #{Project.table_name}.id").
+      references(:project).
+      where("#{table_name}.project_id IS NULL OR (#{base})")
 
     if user.admin?
       scope.where("#{table_name}.visibility <> ? OR #{table_name}.user_id = ?", VISIBILITY_PRIVATE, user.id)
@@ -132,17 +134,17 @@ class IssueQuery < Query
     if project
       principals += project.principals.sort
       unless project.leaf?
-        subprojects = project.descendants.visible.all
+        subprojects = project.descendants.visible.to_a
         principals += Principal.member_of(subprojects)
       end
-      versions = project.shared_versions.all
-      categories = project.issue_categories.all
+      versions = project.shared_versions.to_a
+      categories = project.issue_categories.to_a
       issue_custom_fields = project.all_issue_custom_fields
     else
       if all_projects.any?
         principals += Principal.member_of(all_projects)
       end
-      versions = Version.visible.where(:sharing => 'system').all
+      versions = Version.visible.where(:sharing => 'system').to_a
       issue_custom_fields = IssueCustomField.where(:is_for_all => true)
     end
     principals.uniq!
@@ -338,7 +340,7 @@ class IssueQuery < Query
       scope = scope.preload(:author)
     end
 
-    issues = scope.all
+    issues = scope.to_a
 
     if has_column?(:spent_hours)
       Issue.load_visible_spent_hours(issues)
@@ -359,12 +361,13 @@ class IssueQuery < Query
       joins(:status, :project).
       where(statement).
       includes(([:status, :project] + (options[:include] || [])).uniq).
+      references(([:status, :project] + (options[:include] || [])).uniq).
       where(options[:conditions]).
       order(order_option).
       joins(joins_for_order_statement(order_option.join(','))).
       limit(options[:limit]).
       offset(options[:offset]).
-      find_ids
+      pluck(:id)
   rescue ::ActiveRecord::StatementInvalid => e
     raise StatementInvalid.new(e.message)
   end
@@ -379,7 +382,7 @@ class IssueQuery < Query
       limit(options[:limit]).
       offset(options[:offset]).
       preload(:details, :user, {:issue => [:project, :author, :tracker, :status]}).
-      all
+      to_a
   rescue ::ActiveRecord::StatementInvalid => e
     raise StatementInvalid.new(e.message)
   end
@@ -391,7 +394,8 @@ class IssueQuery < Query
       where(project_statement).
       where(options[:conditions]).
       includes(:project).
-      all
+      references(:project).
+      to_a
   rescue ::ActiveRecord::StatementInvalid => e
     raise StatementInvalid.new(e.message)
   end
@@ -410,7 +414,7 @@ class IssueQuery < Query
       groups = Group.all
       operator = '!' # Override the operator since we want to find by assigned_to
     else
-      groups = Group.where(:id => value).all
+      groups = Group.where(:id => value).to_a
     end
     groups ||= []
 
@@ -430,7 +434,7 @@ class IssueQuery < Query
         " WHERE #{Member.table_name}.project_id = #{Issue.table_name}.project_id))"
     when "=", "!"
       role_cond = value.any? ?
-        "#{MemberRole.table_name}.role_id IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")" :
+        "#{MemberRole.table_name}.role_id IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + ")" :
         "1=0"
 
       sw = operator == "!" ? 'NOT' : ''
@@ -442,7 +446,7 @@ class IssueQuery < Query
 
   def sql_for_is_private_field(field, operator, value)
     op = (operator == "=" ? 'IN' : 'NOT IN')
-    va = value.map {|v| v == '0' ? connection.quoted_false : connection.quoted_true}.uniq.join(',')
+    va = value.map {|v| v == '0' ? self.class.connection.quoted_false : self.class.connection.quoted_true}.uniq.join(',')
 
     "#{Issue.table_name}.is_private #{op} (#{va})"
   end
@@ -461,14 +465,14 @@ class IssueQuery < Query
     sql = case operator
       when "*", "!*"
         op = (operator == "*" ? 'IN' : 'NOT IN')
-        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}')"
+        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}')"
       when "=", "!"
         op = (operator == "=" ? 'IN' : 'NOT IN')
-        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})"
+        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})"
       when "=p", "=!p", "!p"
         op = (operator == "!p" ? 'NOT IN' : 'IN')
         comp = (operator == "=!p" ? '<>' : '=')
-        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})"
+        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})"
       end
 
     if relation_options[:sym] == field && !options[:reverse]
diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb
index d19ff50..ba0624a 100644
--- a/app/models/issue_status.rb
+++ b/app/models/issue_status.rb
@@ -27,6 +27,7 @@ class IssueStatus < ActiveRecord::Base
   validates_uniqueness_of :name
   validates_length_of :name, :maximum => 30
   validates_inclusion_of :default_done_ratio, :in => 0..100, :allow_nil => true
+  attr_protected :id
 
   scope :sorted, lambda { order("#{table_name}.position ASC") }
   scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
@@ -79,7 +80,7 @@ class IssueStatus < ActiveRecord::Base
         includes(:new_status).
         where(["role_id IN (:role_ids) AND tracker_id = :tracker_id AND (#{conditions})",
           {:role_ids => roles.collect(&:id), :tracker_id => tracker.id, :true => true, :false => false}
-          ]).all.
+          ]).to_a.
         map(&:new_status).compact.sort
     else
       []
diff --git a/app/models/journal.rb b/app/models/journal.rb
index 10ebf8e..543da42 100644
--- a/app/models/journal.rb
+++ b/app/models/journal.rb
@@ -24,6 +24,7 @@ class Journal < ActiveRecord::Base
   belongs_to :user
   has_many :details, :class_name => "JournalDetail", :dependent => :delete_all
   attr_accessor :indice
+  attr_protected :id
 
   acts_as_event :title => Proc.new {|o| status = ((s = o.new_status) ? " (#{s})" : nil); "#{o.issue.tracker} ##{o.issue.id}#{status}: #{o.issue.subject}" },
                 :description => :notes,
@@ -34,17 +35,18 @@ class Journal < ActiveRecord::Base
 
   acts_as_activity_provider :type => 'issues',
                             :author_key => :user_id,
-                            :find_options => {:include => [{:issue => :project}, :details, :user],
-                                              :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" +
-                                                             " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"}
+                            :scope => preload({:issue => :project}, :user).
+                                      joins("LEFT OUTER JOIN #{JournalDetail.table_name} ON #{JournalDetail.table_name}.journal_id = #{Journal.table_name}.id").
+                                      where("#{Journal.table_name}.journalized_type = 'Issue' AND" +
+                                            " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')")
 
   before_create :split_private_notes
   after_create :send_notification
 
   scope :visible, lambda {|*args|
     user = args.shift || User.current
-
-    includes(:issue => :project).
+    joins(:issue => :project).
+    references(:project).
       where(Issue.visible_condition(user, *args)).
       where("(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes, *args)}))", false)
   }
@@ -80,15 +82,20 @@ class Journal < ActiveRecord::Base
     end
   end
 
+  # Returns the JournalDetail for the given attribute, or nil if the attribute
+  # was not updated
+  def detail_for_attribute(attribute)
+    details.detect {|detail| detail.prop_key == attribute}
+  end
+
   # Returns the new status if the journal contains a status change, otherwise nil
   def new_status
-    c = details.detect {|detail| detail.prop_key == 'status_id'}
-    (c && c.value) ? IssueStatus.find_by_id(c.value.to_i) : nil
+    s = new_value_for('status_id')
+    s ? IssueStatus.find_by_id(s.to_i) : nil
   end
 
   def new_value_for(prop)
-    c = details.detect {|detail| detail.prop_key == prop}
-    c ? c.value : nil
+    detail_for_attribute(prop).try(:value)
   end
 
   def editable_by?(usr)
@@ -185,6 +192,7 @@ class Journal < ActiveRecord::Base
     if notify? && (Setting.notified_events.include?('issue_updated') ||
         (Setting.notified_events.include?('issue_note_added') && notes.present?) ||
         (Setting.notified_events.include?('issue_status_updated') && new_status.present?) ||
+        (Setting.notified_events.include?('issue_assigned_to_updated') && detail_for_attribute('assigned_to_id').present?) ||
         (Setting.notified_events.include?('issue_priority_updated') && new_value_for('priority_id').present?)
       )
       Mailer.deliver_issue_edit(self)
diff --git a/app/models/journal_detail.rb b/app/models/journal_detail.rb
index 2557ce8..e67c198 100644
--- a/app/models/journal_detail.rb
+++ b/app/models/journal_detail.rb
@@ -18,6 +18,7 @@
 class JournalDetail < ActiveRecord::Base
   belongs_to :journal
   before_save :normalize_values
+  attr_protected :id
 
   def custom_field
     if property == 'cf'
diff --git a/app/models/mail_handler.rb b/app/models/mail_handler.rb
index 702befc..a602433 100644
--- a/app/models/mail_handler.rb
+++ b/app/models/mail_handler.rb
@@ -42,10 +42,18 @@ class MailHandler < ActionMailer::Base
     @@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1')
     @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
 
-    email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
+    email.force_encoding('ASCII-8BIT')
     super(email)
   end
 
+  # Receives an email and rescues any exception
+  def self.safe_receive(*args)
+    receive(*args)
+  rescue => e
+    logger.error "An unexpected error occurred when receiving email: #{e.message}" if logger
+    return false
+  end
+
   # Extracts MailHandler options from environment variables
   # Use when receiving emails with rake tasks
   def self.extract_options_from_env(env)
@@ -66,7 +74,7 @@ class MailHandler < ActionMailer::Base
   cattr_accessor :ignored_emails_headers
   @@ignored_emails_headers = {
     'X-Auto-Response-Suppress' => 'oof',
-    'Auto-Submitted' => /^auto-/
+    'Auto-Submitted' => /\Aauto-(replied|generated)/
   }
 
   # Processes incoming emails
@@ -409,12 +417,11 @@ class MailHandler < ActionMailer::Base
             end
 
     parts.reject! do |part|
-      part.header[:content_disposition].try(:disposition_type) == 'attachment'
+      part.attachment?
     end
 
     @plain_text_body = parts.map do |p|
-      body_charset = p.charset.respond_to?(:force_encoding) ?
-                       Mail::RubyVer.pick_encoding(p.charset).to_s : p.charset
+      body_charset = Mail::RubyVer.pick_encoding(p.charset).to_s
       Redmine::CodesetUtil.to_utf8(p.body.decoded, body_charset)
     end.join("\r\n")
 
diff --git a/app/models/member.rb b/app/models/member.rb
index 6ec22d4..74d6985 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -25,6 +25,7 @@ class Member < ActiveRecord::Base
   validates_presence_of :principal, :project
   validates_uniqueness_of :user_id, :scope => :project_id
   validate :validate_role
+  attr_protected :id
 
   before_destroy :set_issue_category_nil
 
@@ -101,7 +102,7 @@ class Member < ActiveRecord::Base
     end
   end
 
-  # Find or initilize a Member with an id, attributes, and for a Principal
+  # Find or initialize a Member with an id, attributes, and for a Principal
   def self.edit_membership(id, new_attributes, principal=nil)
     @membership = id.present? ? Member.find(id) : Member.new(:principal => principal)
     @membership.attributes = new_attributes
diff --git a/app/models/member_role.rb b/app/models/member_role.rb
index 74d4c63..0385090 100644
--- a/app/models/member_role.rb
+++ b/app/models/member_role.rb
@@ -26,6 +26,7 @@ class MemberRole < ActiveRecord::Base
 
   validates_presence_of :role
   validate :validate_role_member
+  attr_protected :id
 
   def validate_role_member
     errors.add :role_id, :invalid if role && !role.member?
diff --git a/app/models/message.rb b/app/models/message.rb
index 576be47..028a3eb 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -22,9 +22,10 @@ class Message < ActiveRecord::Base
   acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
   acts_as_attachable
   belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
+  attr_protected :id
 
   acts_as_searchable :columns => ['subject', 'content'],
-                     :include => {:board => :project},
+                     :scope => preload(:board => :project),
                      :project_key => "#{Board.table_name}.project_id",
                      :date_column => "#{table_name}.created_on"
   acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
@@ -34,7 +35,7 @@ class Message < ActiveRecord::Base
                 :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
                                                                                                                                        {:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
 
-  acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
+  acts_as_activity_provider :scope => preload({:board => :project}, :author),
                             :author_key => :author_id
   acts_as_watchable
 
@@ -48,7 +49,9 @@ class Message < ActiveRecord::Base
   after_create :send_notification
 
   scope :visible, lambda {|*args|
-    includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
+    joins(:board => :project).
+    references(:board => :project).
+    where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
   }
 
   safe_attributes 'subject', 'content'
diff --git a/app/models/news.rb b/app/models/news.rb
index b86e3f6..baaa92f 100644
--- a/app/models/news.rb
+++ b/app/models/news.rb
@@ -19,16 +19,18 @@ class News < ActiveRecord::Base
   include Redmine::SafeAttributes
   belongs_to :project
   belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
-  has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
+  has_many :comments, lambda {order("created_on")}, :as => :commented, :dependent => :delete_all
 
   validates_presence_of :title, :description
   validates_length_of :title, :maximum => 60
   validates_length_of :summary, :maximum => 255
+  attr_protected :id
 
   acts_as_attachable :delete_permission => :manage_news
-  acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
+  acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"],
+                     :scope => preload(:project)
   acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
-  acts_as_activity_provider :find_options => {:include => [:project, :author]},
+  acts_as_activity_provider :scope => preload(:project, :author),
                             :author_key => :author_id
   acts_as_watchable
 
@@ -36,7 +38,9 @@ class News < ActiveRecord::Base
   after_create :send_notification
 
   scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
+    joins(:project).
+    references([:author, :project]).
+    where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
   }
 
   safe_attributes 'title', 'summary', 'description'
@@ -68,7 +72,7 @@ class News < ActiveRecord::Base
 
   # returns latest news for projects visible by user
   def self.latest(user = User.current, count = 5)
-    visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
+    visible(user).joins([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).to_a
   end
 
   private
diff --git a/app/models/principal.rb b/app/models/principal.rb
index ea4b00f..fb1905e 100644
--- a/app/models/principal.rb
+++ b/app/models/principal.rb
@@ -25,11 +25,13 @@ class Principal < ActiveRecord::Base
   STATUS_LOCKED     = 3
 
   has_many :members, :foreign_key => 'user_id', :dependent => :destroy
-  has_many :memberships, :class_name => 'Member',
-           :foreign_key => 'user_id',
-           :include => [:project, :roles],
-           :conditions => "#{Project.table_name}.status<>#{Project::STATUS_ARCHIVED}",
-           :order => "#{Project.table_name}.name"
+  has_many :memberships,
+           lambda {preload(:project, :roles).
+                   joins(:project).
+                   where("#{Project.table_name}.status<>#{Project::STATUS_ARCHIVED}").
+                   order("#{Project.table_name}.name")},
+           :class_name => 'Member',
+           :foreign_key => 'user_id'
   has_many :projects, :through => :memberships
   has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
 
@@ -56,12 +58,12 @@ class Principal < ActiveRecord::Base
 
   # Principals that are members of a collection of projects
   scope :member_of, lambda {|projects|
-    projects = [projects] unless projects.is_a?(Array)
-    if projects.empty?
+    projects = [projects] if projects.is_a?(Project)
+    if projects.blank?
       where("1=0")
     else
       ids = projects.map(&:id)
-      active.uniq.joins(:members).where("#{Member.table_name}.project_id IN (?)", ids)
+      active.where("#{Principal.table_name}.id IN (SELECT DISTINCT user_id FROM #{Member.table_name} WHERE project_id IN (?))", ids)
     end
   }
   # Principals that are not members of projects
diff --git a/app/models/project.rb b/app/models/project.rb
index fd9d647..b602732 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -26,33 +26,37 @@ class Project < ActiveRecord::Base
   # Maximum length for project identifiers
   IDENTIFIER_MAX_LENGTH = 100
 
-  # Specific overidden Activities
+  # Specific overridden Activities
   has_many :time_entry_activities
-  has_many :members, :include => [:principal, :roles], :conditions => "#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}"
+  has_many :members,
+           lambda { joins(:principal, :roles).
+                    references(:principal, :roles).
+                    where("#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}") }
   has_many :memberships, :class_name => 'Member'
-  has_many :member_principals, :class_name => 'Member',
-                               :include => :principal,
-                               :conditions => "#{Principal.table_name}.type='Group' OR (#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE})"
-
+  has_many :member_principals,
+           lambda { joins(:principal).
+                    references(:principal).
+                    where("#{Principal.table_name}.type='Group' OR (#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE})")},
+    :class_name => 'Member'
   has_many :enabled_modules, :dependent => :delete_all
-  has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
-  has_many :issues, :dependent => :destroy, :include => [:status, :tracker]
+  has_and_belongs_to_many :trackers, lambda {order("#{Tracker.table_name}.position")}
+  has_many :issues, :dependent => :destroy
   has_many :issue_changes, :through => :issues, :source => :journals
-  has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
+  has_many :versions, lambda {order("#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC")}, :dependent => :destroy
   has_many :time_entries, :dependent => :destroy
   has_many :queries, :class_name => 'IssueQuery', :dependent => :delete_all
   has_many :documents, :dependent => :destroy
-  has_many :news, :dependent => :destroy, :include => :author
-  has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
-  has_many :boards, :dependent => :destroy, :order => "position ASC"
-  has_one :repository, :conditions => ["is_default = ?", true]
+  has_many :news, lambda {includes(:author)}, :dependent => :destroy
+  has_many :issue_categories, lambda {order("#{IssueCategory.table_name}.name")}, :dependent => :delete_all
+  has_many :boards, lambda {order("position ASC")}, :dependent => :destroy
+  has_one :repository, lambda {where(["is_default = ?", true])}
   has_many :repositories, :dependent => :destroy
   has_many :changesets, :through => :repository
   has_one :wiki, :dependent => :destroy
   # Custom field for the project issues
   has_and_belongs_to_many :issue_custom_fields,
+                          lambda {order("#{CustomField.table_name}.position")},
                           :class_name => 'IssueCustomField',
-                          :order => "#{CustomField.table_name}.position",
                           :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
                           :association_foreign_key => 'custom_field_id'
 
@@ -74,7 +78,7 @@ class Project < ActiveRecord::Base
   validates_length_of :name, :maximum => 255
   validates_length_of :homepage, :maximum => 255
   validates_length_of :identifier, :in => 1..IDENTIFIER_MAX_LENGTH
-  # donwcase letters, digits, dashes but not digits only
+  # downcase letters, digits, dashes but not digits only
   validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :if => Proc.new { |p| p.identifier_changed? }
   # reserved words
   validates_exclusion_of :identifier, :in => %w( new )
@@ -126,9 +130,9 @@ class Project < ActiveRecord::Base
     if !initialized.key?('trackers') && !initialized.key?('tracker_ids')
       default = Setting.default_projects_tracker_ids
       if default.is_a?(Array)
-        self.trackers = Tracker.where(:id => default.map(&:to_i)).sorted.all
+        self.trackers = Tracker.where(:id => default.map(&:to_i)).sorted.to_a
       else
-        self.trackers = Tracker.sorted.all
+        self.trackers = Tracker.sorted.to_a
       end
     end
   end
@@ -144,7 +148,7 @@ class Project < ActiveRecord::Base
   # returns latest created projects
   # non public projects will be returned only if user is a member of those
   def self.latest(user=nil, count=5)
-    visible(user).limit(count).order("created_on DESC").all
+    visible(user).limit(count).order("created_on DESC").to_a
   end
 
   # Returns true if the project is visible to +user+ or to the current user.
@@ -252,10 +256,10 @@ class Project < ActiveRecord::Base
       parent_activity = TimeEntryActivity.find(activity['parent_id'])
       activity['name'] = parent_activity.name
       activity['position'] = parent_activity.position
-      if Enumeration.overridding_change?(activity, parent_activity)
+      if Enumeration.overriding_change?(activity, parent_activity)
         project_activity = self.time_entry_activities.create(activity)
         if project_activity.new_record?
-          raise ActiveRecord::Rollback, "Overridding TimeEntryActivity was not successfully saved"
+          raise ActiveRecord::Rollback, "Overriding TimeEntryActivity was not successfully saved"
         else
           self.time_entries.
             where(["activity_id = ?", parent_activity.id]).
@@ -359,7 +363,7 @@ class Project < ActiveRecord::Base
   # by the current user
   def allowed_parents
     return @allowed_parents if @allowed_parents
-    @allowed_parents = Project.where(Project.allowed_to_condition(User.current, :add_subprojects)).all
+    @allowed_parents = Project.where(Project.allowed_to_condition(User.current, :add_subprojects)).to_a
     @allowed_parents = @allowed_parents - self_and_descendants
     if User.current.allowed_to?(:add_project, nil, :global => true) || (!new_record? && parent.nil?)
       @allowed_parents << nil
@@ -430,11 +434,12 @@ class Project < ActiveRecord::Base
     @rolled_up_trackers ||=
       Tracker.
         joins(:projects).
+        references(:project).
         joins("JOIN #{EnabledModule.table_name} ON #{EnabledModule.table_name}.project_id = #{Project.table_name}.id AND #{EnabledModule.table_name}.name = 'issue_tracking'").
         select("DISTINCT #{Tracker.table_name}.*").
         where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> #{STATUS_ARCHIVED}", lft, rgt).
         sorted.
-        all
+        to_a
   end
 
   # Closes open and locked project versions that are completed
@@ -452,7 +457,8 @@ class Project < ActiveRecord::Base
   def rolled_up_versions
     @rolled_up_versions ||=
       Version.
-        includes(:project).
+        joins(:project).
+        references(:project).
         where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> ?", lft, rgt, STATUS_ARCHIVED)
   end
 
@@ -460,13 +466,17 @@ class Project < ActiveRecord::Base
   def shared_versions
     if new_record?
       Version.
-        includes(:project).
+        joins(:project).
+        references(:project).
+        preload(:project).
         where("#{Project.table_name}.status <> ? AND #{Version.table_name}.sharing = 'system'", STATUS_ARCHIVED)
     else
       @shared_versions ||= begin
         r = root? ? self : root
         Version.
-          includes(:project).
+          joins(:project).
+          references(:project).
+          preload(:project).
           where("#{Project.table_name}.id = #{id}" +
                   " OR (#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED} AND (" +
                     " #{Version.table_name}.sharing = 'system'" +
@@ -492,7 +502,7 @@ class Project < ActiveRecord::Base
   # Deletes all project's members
   def delete_all_members
     me, mr = Member.table_name, MemberRole.table_name
-    connection.delete("DELETE FROM #{mr} WHERE #{mr}.member_id IN (SELECT #{me}.id FROM #{me} WHERE #{me}.project_id = #{id})")
+    self.class.connection.delete("DELETE FROM #{mr} WHERE #{mr}.member_id IN (SELECT #{me}.id FROM #{me} WHERE #{me}.project_id = #{id})")
     Member.delete_all(['project_id = ?', id])
   end
 
@@ -502,7 +512,7 @@ class Project < ActiveRecord::Base
     assignable.select {|m| m.roles.detect {|role| role.assignable?}}.collect {|m| m.principal}.sort
   end
 
-  # Returns the mail adresses of users that should be always notified on project events
+  # Returns the mail addresses of users that should be always notified on project events
   def recipients
     notified_users.collect {|user| user.mail}
   end
@@ -514,7 +524,7 @@ class Project < ActiveRecord::Base
   end
 
   # Returns a scope of all custom fields enabled for project issues
-  # (explictly associated custom fields and custom fields enabled for all projects)
+  # (explicitly associated custom fields and custom fields enabled for all projects)
   def all_issue_custom_fields
     @all_issue_custom_fields ||= IssueCustomField.
       sorted.
@@ -718,7 +728,7 @@ class Project < ActiveRecord::Base
     project = project.is_a?(Project) ? project : Project.find(project)
 
     to_be_copied = %w(wiki versions issue_categories issues members queries boards)
-    to_be_copied = to_be_copied & options[:only].to_a unless options[:only].nil?
+    to_be_copied = to_be_copied & Array.wrap(options[:only]) unless options[:only].nil?
 
     Project.transaction do
       if save
@@ -730,6 +740,7 @@ class Project < ActiveRecord::Base
         save
       end
     end
+    true
   end
 
   # Returns a new unsaved Project instance with attributes copied from +project+
@@ -847,7 +858,7 @@ class Project < ActiveRecord::Base
   # Copies issues from +project+
   def copy_issues(project)
     # Stores the source issue id as a key and the copied issues as the
-    # value.  Used to map the two togeather for issue relations.
+    # value.  Used to map the two together for issue relations.
     issues_map = {}
 
     # Store status and reopen locked/closed versions
diff --git a/app/models/query.rb b/app/models/query.rb
index 4493616..a4d34d1 100644
--- a/app/models/query.rb
+++ b/app/models/query.rb
@@ -57,6 +57,10 @@ class QueryColumn
     object.send name
   end
 
+  def value_object(object)
+    object.send name
+  end
+
   def css_classes
     name
   end
@@ -80,10 +84,21 @@ class QueryCustomFieldColumn < QueryColumn
     @cf
   end
 
-  def value(object)
+  def value_object(object)
     if custom_field.visible_by?(object.project, User.current)
-      cv = object.custom_values.select {|v| v.custom_field_id == @cf.id}.collect {|v| @cf.cast_value(v.value)}
-      cv.size > 1 ? cv.sort {|a,b| a.to_s <=> b.to_s} : cv.first
+      cv = object.custom_values.select {|v| v.custom_field_id == @cf.id}
+      cv.size > 1 ? cv.sort {|a,b| a.value.to_s <=> b.value.to_s} : cv.first
+    else
+      nil
+    end
+  end
+
+  def value(object)
+    raw = value_object(object)
+    if raw.is_a?(Array)
+      raw.map {|r| @cf.cast_value(r.value)}
+    elsif raw
+      @cf.cast_value(raw.value)
     else
       nil
     end
@@ -105,7 +120,7 @@ class QueryAssociationCustomFieldColumn < QueryCustomFieldColumn
     @association = association
   end
 
-  def value(object)
+  def value_object(object)
     if assoc = object.send(@association)
       super(assoc)
     end
@@ -144,8 +159,8 @@ class Query < ActiveRecord::Base
 
   after_save do |query|
     if query.visibility_changed? && query.visibility != VISIBILITY_ROLES
-	    query.roles.clear
-	  end
+      query.roles.clear
+    end
   end
 
   class_attribute :operators
@@ -273,7 +288,7 @@ class Query < ActiveRecord::Base
   end
 
   def trackers
-    @trackers ||= project.nil? ? Tracker.sorted.all : project.rolled_up_trackers
+    @trackers ||= project.nil? ? Tracker.sorted.to_a : project.rolled_up_trackers
   end
 
   # Returns a hash of localized labels for all filter operators
@@ -291,7 +306,7 @@ class Query < ActiveRecord::Base
   end
 
   def all_projects
-    @all_projects ||= Project.visible.all
+    @all_projects ||= Project.visible.to_a
   end
 
   def all_projects_values
@@ -541,7 +556,7 @@ class Query < ActiveRecord::Base
       next unless v and !v.empty?
       operator = operator_for(field)
 
-      # "me" value subsitution
+      # "me" value substitution
       if %w(assigned_to_id author_id user_id watcher_id).include?(field)
         if v.delete("me")
           if User.current.logged?
@@ -640,7 +655,7 @@ class Query < ActiveRecord::Base
             sql = "#{db_table}.#{db_field} BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5}"
           end
         else
-          sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
+          sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + ")"
         end
       else
         # IN an empty set
@@ -648,7 +663,7 @@ class Query < ActiveRecord::Base
       end
     when "!"
       if value.any?
-        sql = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))"
+        sql = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + "))"
       else
         # NOT IN an empty set
         sql = "1=1"
@@ -690,9 +705,9 @@ class Query < ActiveRecord::Base
         end
       end
     when "o"
-      sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{connection.quoted_false})" if field == "status_id"
+      sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_false})" if field == "status_id"
     when "c"
-      sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{connection.quoted_true})" if field == "status_id"
+      sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_true})" if field == "status_id"
     when "><t-"
       # between today - n days and today
       sql = relative_date_clause(db_table, db_field, - value.first.to_i, 0)
@@ -754,9 +769,9 @@ class Query < ActiveRecord::Base
       date = Date.today
       sql = date_clause(db_table, db_field, date.beginning_of_year, date.end_of_year)
     when "~"
-      sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
+      sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{self.class.connection.quote_string(value.first.to_s.downcase)}%'"
     when "!~"
-      sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
+      sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{self.class.connection.quote_string(value.first.to_s.downcase)}%'"
     else
       raise "Unknown query operator #{operator}"
     end
@@ -819,7 +834,7 @@ class Query < ActiveRecord::Base
       if self.class.default_timezone == :utc
         from = from.utc
       end
-      s << ("#{table}.#{field} > '%s'" % [connection.quoted_date(from)])
+      s << ("#{table}.#{field} > '%s'" % [self.class.connection.quoted_date(from)])
     end
     if to
       if to.is_a?(Date)
@@ -828,7 +843,7 @@ class Query < ActiveRecord::Base
       if self.class.default_timezone == :utc
         to = to.utc
       end
-      s << ("#{table}.#{field} <= '%s'" % [connection.quoted_date(to)])
+      s << ("#{table}.#{field} <= '%s'" % [self.class.connection.quoted_date(to)])
     end
     s.join(' AND ')
   end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 1b469c0..4cc960e 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -25,7 +25,7 @@ class Repository < ActiveRecord::Base
   IDENTIFIER_MAX_LENGTH = 255
 
   belongs_to :project
-  has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
+  has_many :changesets, lambda{order("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC")}
   has_many :filechanges, :class_name => 'Change', :through => :changesets
 
   serialize :extra_info
@@ -45,6 +45,7 @@ class Repository < ActiveRecord::Base
   validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
   # Checks if the SCM is enabled when creating a repository
   validate :repo_create_validation, :on => :create
+  attr_protected :id
 
   safe_attributes 'identifier',
     'login',
@@ -264,7 +265,7 @@ class Repository < ActiveRecord::Base
         reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC").
         limit(limit).
         preload(:user).
-        all
+        to_a
     else
       filechanges.
         where("path = ?", path.with_leading_slash).
@@ -313,7 +314,8 @@ class Repository < ActiveRecord::Base
       return @found_committer_users[committer] if @found_committer_users.has_key?(committer)
 
       user = nil
-      c = changesets.where(:committer => committer).includes(:user).first
+      c = changesets.where(:committer => committer).
+            includes(:user).references(:user).first
       if c && c.user
         user = c.user
       elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
@@ -435,10 +437,10 @@ class Repository < ActiveRecord::Base
     ci = "#{table_name_prefix}changesets_issues#{table_name_suffix}"
     cp = "#{table_name_prefix}changeset_parents#{table_name_suffix}"
 
-    connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
-    connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
-    connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
-    connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
+    self.class.connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
+    self.class.connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
+    self.class.connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
+    self.class.connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
     clear_extra_info_of_changesets
   end
 
diff --git a/app/models/repository/cvs.rb b/app/models/repository/cvs.rb
index 2918c79..abc4083 100644
--- a/app/models/repository/cvs.rb
+++ b/app/models/repository/cvs.rb
@@ -138,9 +138,9 @@ class Repository::Cvs < Repository
         # is not exclusive at all.
         tmp_time = revision.time.clone
         unless filechanges.find_by_path_and_revision(
-	                         scm.with_leading_slash(revision.paths[0][:path]),
-	                         revision.paths[0][:revision]
-	                           )
+                                scm.with_leading_slash(revision.paths[0][:path]),
+                                revision.paths[0][:revision]
+                             )
           cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
           author_utf8 = Changeset.to_utf8(revision.author, repo_log_encoding)
           cs  = changesets.where(
@@ -150,7 +150,7 @@ class Repository::Cvs < Repository
                 ).first
           # create a new changeset....
           unless cs
-            # we use a temporaray revision number here (just for inserting)
+            # we use a temporary revision number here (just for inserting)
             # later on, we calculate a continous positive number
             tmp_time2 = tmp_time.clone.gmtime
             branch    = revision.paths[0][:branch]
@@ -199,7 +199,7 @@ class Repository::Cvs < Repository
     # Need to retrieve existing revision numbers to sort them as integers
     sql = "SELECT revision FROM #{Changeset.table_name} "
     sql << "WHERE repository_id = #{id} AND revision NOT LIKE 'tmp%'"
-    @current_revision_number ||= (connection.select_values(sql).collect(&:to_i).max || 0)
+    @current_revision_number ||= (self.class.connection.select_values(sql).collect(&:to_i).max || 0)
     @current_revision_number += 1
   end
 end
diff --git a/app/models/repository/git.rb b/app/models/repository/git.rb
index c51a7e5..978944e 100644
--- a/app/models/repository/git.rb
+++ b/app/models/repository/git.rb
@@ -241,7 +241,7 @@ class Repository::Git < Repository
   def latest_changesets(path,rev,limit=10)
     revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false)
     return [] if revisions.nil? || revisions.empty?
-    changesets.where(:scmid => revisions.map {|c| c.scmid}).all
+    changesets.where(:scmid => revisions.map {|c| c.scmid}).to_a
   end
 
   def clear_extra_info_of_changesets
diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb
index f9339d8..81dd24d 100644
--- a/app/models/repository/mercurial.rb
+++ b/app/models/repository/mercurial.rb
@@ -20,7 +20,7 @@ require 'redmine/scm/adapters/mercurial_adapter'
 class Repository::Mercurial < Repository
   # sort changesets by revision number
   has_many :changesets,
-           :order       => "#{Changeset.table_name}.id DESC",
+           lambda {order("#{Changeset.table_name}.id DESC")},
            :foreign_key => 'repository_id'
 
   attr_protected        :root_url
@@ -117,9 +117,10 @@ class Repository::Mercurial < Repository
     changesets.
       includes(:user).
       where(latest_changesets_cond(path, rev, limit)).
+      references(:user).
       limit(limit).
       order("#{Changeset.table_name}.id DESC").
-      all
+      to_a
   end
 
   def is_short_id_in_db?
@@ -155,7 +156,7 @@ class Repository::Mercurial < Repository
       # Revisions in root directory and sub directory are not equal.
       # So, in order to get correct limit, we need to get all revisions.
       # But, it is very heavy.
-      # Mercurial does not treat direcotry.
+      # Mercurial does not treat directory.
       # So, "hg log DIR" is very heavy.
       branch_limit = path.blank? ? limit : ( limit * 5 )
       args << nodes_in_branch(rev, branch_limit)
diff --git a/app/models/repository/subversion.rb b/app/models/repository/subversion.rb
index 532c1f3..1659b77 100644
--- a/app/models/repository/subversion.rb
+++ b/app/models/repository/subversion.rb
@@ -42,7 +42,7 @@ class Repository::Subversion < Repository
     revisions = scm.revisions(path, rev, nil, :limit => limit)
     if revisions
       identifiers = revisions.collect(&:identifier).compact
-      changesets.where(:revision => identifiers).reorder("committed_on DESC").includes(:repository, :user).all
+      changesets.where(:revision => identifiers).reorder("committed_on DESC").includes(:repository, :user).to_a
     else
       []
     end
diff --git a/app/models/role.rb b/app/models/role.rb
index 1097761..efd9a33 100644
--- a/app/models/role.rb
+++ b/app/models/role.rb
@@ -166,7 +166,7 @@ class Role < ActiveRecord::Base
 
   # Find all the roles that can be given to a project member
   def self.find_all_givable
-    Role.givable.all
+    Role.givable.to_a
   end
 
   # Return the builtin 'non member' role.  If the role doesn't exist,
diff --git a/app/models/setting.rb b/app/models/setting.rb
index 532e9d4..3881f90 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -86,6 +86,7 @@ class Setting < ActiveRecord::Base
   validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting|
     (s = @@available_settings[setting.name]) && s['format'] == 'int'
   }
+  attr_protected :id
 
   # Hash used to cache setting values
   @cached_settings = {}
@@ -142,6 +143,7 @@ END_SRC
   def self.set_from_params(name, params)
     params = params.dup
     params.delete_if {|v| v.blank? } if params.is_a?(Array)
+    params.symbolize_keys! if params.is_a?(Hash)
 
     m = "#{name}_from_params"
     if respond_to? m
diff --git a/app/models/time_entry.rb b/app/models/time_entry.rb
index cfca476..ef0700d 100644
--- a/app/models/time_entry.rb
+++ b/app/models/time_entry.rb
@@ -35,7 +35,7 @@ class TimeEntry < ActiveRecord::Base
 
   acts_as_activity_provider :timestamp => "#{table_name}.created_on",
                             :author_key => :user_id,
-                            :find_options => {:include => :project}
+                            :scope => preload(:project)
 
   validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on
   validates_numericality_of :hours, :allow_nil => true, :message => :invalid
@@ -45,13 +45,19 @@ class TimeEntry < ActiveRecord::Base
   validate :validate_time_entry
 
   scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_time_entries, *args))
+    joins(:project).
+    references(:project).
+    where(Project.allowed_to_condition(args.shift || User.current, :view_time_entries, *args))
   }
   scope :on_issue, lambda {|issue|
-    includes(:issue).where("#{Issue.table_name}.root_id = #{issue.root_id} AND #{Issue.table_name}.lft >= #{issue.lft} AND #{Issue.table_name}.rgt <= #{issue.rgt}")
+    joins(:issue).
+    references(:issue).
+    where("#{Issue.table_name}.root_id = #{issue.root_id} AND #{Issue.table_name}.lft >= #{issue.lft} AND #{Issue.table_name}.rgt <= #{issue.rgt}")
   }
   scope :on_project, lambda {|project, include_subprojects|
-    includes(:project).where(project.project_condition(include_subprojects))
+    joins(:project).
+    references(:project).
+    where(project.project_condition(include_subprojects))
   }
   scope :spent_between, lambda {|from, to|
     if from && to
diff --git a/app/models/time_entry_query.rb b/app/models/time_entry_query.rb
index bd2eef3..05c39f5 100644
--- a/app/models/time_entry_query.rb
+++ b/app/models/time_entry_query.rb
@@ -42,7 +42,7 @@ class TimeEntryQuery < Query
     if project
       principals += project.principals.sort
       unless project.leaf?
-        subprojects = project.descendants.visible.all
+        subprojects = project.descendants.visible.to_a
         if subprojects.any?
           add_available_filter "subproject_id",
             :type => :list_subprojects,
@@ -109,7 +109,8 @@ class TimeEntryQuery < Query
       where(statement).
       order(order_option).
       joins(joins_for_order_statement(order_option.join(','))).
-      includes(:activity)
+      includes(:activity).
+      references(:activity)
   end
 
   def sql_for_activity_id_field(field, operator, value)
diff --git a/app/models/token.rb b/app/models/token.rb
index b1d2d29..0f37510 100644
--- a/app/models/token.rb
+++ b/app/models/token.rb
@@ -18,6 +18,7 @@
 class Token < ActiveRecord::Base
   belongs_to :user
   validates_uniqueness_of :value
+  attr_protected :id
 
   before_create :delete_previous_tokens, :generate_new_token
 
diff --git a/app/models/tracker.rb b/app/models/tracker.rb
index 20ba845..b4f22c8 100644
--- a/app/models/tracker.rb
+++ b/app/models/tracker.rb
@@ -63,7 +63,7 @@ class Tracker < ActiveRecord::Base
             connection.select_rows("SELECT DISTINCT old_status_id, new_status_id FROM #{WorkflowTransition.table_name} WHERE tracker_id = #{id} AND type = 'WorkflowTransition'").
             flatten.
             uniq
-    @issue_statuses = IssueStatus.where(:id => ids).all.sort
+    @issue_statuses = IssueStatus.where(:id => ids).to_a.sort
   end
 
   def disabled_core_fields
@@ -92,7 +92,7 @@ class Tracker < ActiveRecord::Base
   # Returns the fields that are disabled for all the given trackers
   def self.disabled_core_fields(trackers)
     if trackers.present?
-      trackers.uniq.map(&:disabled_core_fields).reduce(:&)
+      trackers.map(&:disabled_core_fields).reduce(:&)
     else
       []
     end
diff --git a/app/models/user.rb b/app/models/user.rb
index 4a33590..4479de5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -79,8 +79,8 @@ class User < Principal
                           :after_remove => Proc.new {|user, group| group.user_removed(user)}
   has_many :changesets, :dependent => :nullify
   has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
-  has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'"
-  has_one :api_token, :class_name => 'Token', :conditions => "action='api'"
+  has_one :rss_token, lambda {where "action='feeds'"}, :class_name => 'Token'
+  has_one :api_token, lambda {where "action='api'"}, :class_name => 'Token'
   belongs_to :auth_source
 
   scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") }
@@ -105,9 +105,13 @@ class User < Principal
   validates_length_of :firstname, :lastname, :maximum => 30
   validates_format_of :mail, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true
   validates_length_of :mail, :maximum => MAIL_LENGTH_LIMIT, :allow_nil => true
-  validates_confirmation_of :password, :allow_nil => true
   validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true
   validate :validate_password_length
+  validate do
+    if password_confirmation && password != password_confirmation
+      errors.add(:password, :confirmation)
+    end
+  end
 
   before_create :set_mail_notification
   before_save   :generate_password_if_needed, :update_hashed_password
@@ -151,6 +155,15 @@ class User < Principal
     write_attribute(:mail, arg.to_s.strip)
   end
 
+  def self.find_or_initialize_by_identity_url(url)
+    user = where(:identity_url => url).first
+    unless user
+      user = User.new
+      user.identity_url = url
+    end
+    user
+  end
+
   def identity_url=(url)
     if url.blank?
       write_attribute(:identity_url, '')
@@ -549,6 +562,8 @@ class User < Principal
         # Authorize if user is authorized on every element of the array
         context.map {|project| allowed_to?(action, project, options, &block)}.reduce(:&)
       end
+    elsif context
+      raise ArgumentError.new("#allowed_to? context argument must be a Project, an Array of projects or nil")
     elsif options[:global]
       # Admin users are always authorized
       return true if admin?
@@ -626,11 +641,11 @@ class User < Principal
   end
 
   def self.current=(user)
-    Thread.current[:current_user] = user
+    RequestStore.store[:current_user] = user
   end
 
   def self.current
-    Thread.current[:current_user] ||= User.anonymous
+    RequestStore.store[:current_user] ||= User.anonymous
   end
 
   # Returns the anonymous user.  If the anonymous user does not exist, it is created.  There can be only
diff --git a/app/models/version.rb b/app/models/version.rb
index 02061c5..8d6e4cd 100644
--- a/app/models/version.rb
+++ b/app/models/version.rb
@@ -33,11 +33,14 @@ class Version < ActiveRecord::Base
   validates :effective_date, :date => true
   validates_inclusion_of :status, :in => VERSION_STATUSES
   validates_inclusion_of :sharing, :in => VERSION_SHARINGS
+  attr_protected :id
 
   scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
   scope :open, lambda { where(:status => 'open') }
   scope :visible, lambda {|*args|
-    includes(:project).where(Project.allowed_to_condition(args.first || User.current, :view_issues))
+    joins(:project).
+    references(:project).
+    where(Project.allowed_to_condition(args.first || User.current, :view_issues))
   }
 
   safe_attributes 'name',
@@ -256,7 +259,7 @@ class Version < ActiveRecord::Base
 
   # Returns the average estimated time of assigned issues
   # or 1 if no issue has an estimated time
-  # Used to weigth unestimated issues in progress calculation
+  # Used to weight unestimated issues in progress calculation
   def estimated_average
     if @estimated_average.nil?
       average = fixed_issues.average(:estimated_hours).to_f
diff --git a/app/models/watcher.rb b/app/models/watcher.rb
index 1f42de8..9981bea 100644
--- a/app/models/watcher.rb
+++ b/app/models/watcher.rb
@@ -22,6 +22,7 @@ class Watcher < ActiveRecord::Base
   validates_presence_of :user
   validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id]
   validate :validate_user
+  attr_protected :id
 
   # Returns true if at least one object among objects is watched by user
   def self.any_watched?(objects, user)
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index 45a22fd..b1ce297 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -18,13 +18,14 @@
 class Wiki < ActiveRecord::Base
   include Redmine::SafeAttributes
   belongs_to :project
-  has_many :pages, :class_name => 'WikiPage', :dependent => :destroy, :order => 'title'
+  has_many :pages, lambda {order('title')}, :class_name => 'WikiPage', :dependent => :destroy
   has_many :redirects, :class_name => 'WikiRedirect', :dependent => :delete_all
 
   acts_as_watchable
 
   validates_presence_of :start_page
   validates_format_of :start_page, :with => /\A[^,\.\/\?\;\|\:]*\z/
+  attr_protected :id
 
   safe_attributes 'start_page'
 
diff --git a/app/models/wiki_content.rb b/app/models/wiki_content.rb
index 7ed19f2..3eac926 100644
--- a/app/models/wiki_content.rb
+++ b/app/models/wiki_content.rb
@@ -23,6 +23,7 @@ class WikiContent < ActiveRecord::Base
   belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
   validates_presence_of :text
   validates_length_of :comments, :maximum => 255, :allow_nil => true
+  attr_protected :id
 
   acts_as_versioned
 
@@ -40,7 +41,7 @@ class WikiContent < ActiveRecord::Base
     page.nil? ? [] : page.attachments
   end
 
-  # Returns the mail adresses of users that should be notified
+  # Returns the mail addresses of users that should be notified
   def recipients
     notified = project.notified_users
     notified.reject! {|user| !visible?(user)}
@@ -68,13 +69,13 @@ class WikiContent < ActiveRecord::Base
                               :timestamp => "#{WikiContent.versioned_table_name}.updated_on",
                               :author_key => "#{WikiContent.versioned_table_name}.author_id",
                               :permission => :view_wiki_edits,
-                              :find_options => {:select => "#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comments, " +
-                                                           "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title, " +
-                                                           "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
-                                                           "#{WikiContent.versioned_table_name}.id",
-                                                :joins => "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
-                                                          "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " +
-                                                          "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id"}
+                              :scope => select("#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comments, " +
+                                               "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title, " +
+                                               "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " +
+                                               "#{WikiContent.versioned_table_name}.id").
+                                        joins("LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
+                                              "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " +
+                                              "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id")
 
     after_destroy :page_update_after_destroy
 
@@ -104,7 +105,7 @@ class WikiContent < ActiveRecord::Base
                 # uncompressed data
                 data
               end
-        str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
+        str.force_encoding("UTF-8")
         str
       end
     end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index fc56d9d..8aed835 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -33,7 +33,7 @@ class WikiPage < ActiveRecord::Base
                 :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}}
 
   acts_as_searchable :columns => ['title', "#{WikiContent.table_name}.text"],
-                     :include => [{:wiki => :project}, :content],
+                     :scope => preload(:wiki => :project).joins(:content, {:wiki => :project}),
                      :permission => :view_wiki_pages,
                      :project_key => "#{Wiki.table_name}.project_id"
 
@@ -43,6 +43,7 @@ class WikiPage < ActiveRecord::Base
   validates_format_of :title, :with => /\A[^,\.\/\?\;\|\s]*\z/
   validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
   validates_associated :content
+  attr_protected :id
 
   validate :validate_parent_title
   before_destroy :remove_redirects
@@ -180,12 +181,10 @@ class WikiPage < ActiveRecord::Base
   def save_with_content(content)
     ret = nil
     transaction do
-      self.content = content
-      if new_record?
-        # Rails automatically saves associated content
-        ret = save
-      else
-        ret = save && (content.text_changed? ? content.save : true)
+      ret = save
+      if content.text_changed?
+        self.content = content
+        ret = ret && content.changed?
       end
       raise ActiveRecord::Rollback unless ret
     end
diff --git a/app/models/wiki_redirect.rb b/app/models/wiki_redirect.rb
index 403fb5c..1664531 100644
--- a/app/models/wiki_redirect.rb
+++ b/app/models/wiki_redirect.rb
@@ -20,4 +20,5 @@ class WikiRedirect < ActiveRecord::Base
 
   validates_presence_of :title, :redirects_to
   validates_length_of :title, :redirects_to, :maximum => 255
+  attr_protected :id
 end
diff --git a/app/models/workflow_permission.rb b/app/models/workflow_permission.rb
index 0338a3e..d525e2d 100644
--- a/app/models/workflow_permission.rb
+++ b/app/models/workflow_permission.rb
@@ -19,20 +19,43 @@ class WorkflowPermission < WorkflowRule
   validates_inclusion_of :rule, :in => %w(readonly required)
   validate :validate_field_name
 
-  # Replaces the workflow permissions for the given tracker and role
+  # Returns the workflow permissions for the given trackers and roles
+  # grouped by status_id
   #
   # Example:
-  #   WorkflowPermission.replace_permissions role, tracker, {'due_date' => {'1' => 'readonly', '2' => 'required'}}
-  def self.replace_permissions(tracker, role, permissions)
-    destroy_all(:tracker_id => tracker.id, :role_id => role.id)
+  #   WorkflowPermission.rules_by_status_id trackers, roles
+  #   # => {1 => {'start_date' => 'required', 'due_date' => 'readonly'}}
+  def self.rules_by_status_id(trackers, roles)
+    WorkflowPermission.where(:tracker_id => trackers.map(&:id), :role_id => roles.map(&:id)).inject({}) do |h, w|
+      h[w.old_status_id] ||= {}
+      h[w.old_status_id][w.field_name] ||= []
+      h[w.old_status_id][w.field_name] << w.rule
+      h
+    end
+  end
+
+  # Replaces the workflow permissions for the given trackers and roles
+  #
+  # Example:
+  #   WorkflowPermission.replace_permissions trackers, roles, {'1' => {'start_date' => 'required', 'due_date' => 'readonly'}}
+  def self.replace_permissions(trackers, roles, permissions)
+    trackers = Array.wrap trackers
+    roles = Array.wrap roles
 
-    permissions.each { |field, rule_by_status_id|
-      rule_by_status_id.each { |status_id, rule|
-        if rule.present?
-          WorkflowPermission.create(:role_id => role.id, :tracker_id => tracker.id, :old_status_id => status_id, :field_name => field, :rule => rule)
-        end
+    transaction do
+      permissions.each { |status_id, rule_by_field|
+        rule_by_field.each { |field, rule|
+          destroy_all(:tracker_id => trackers.map(&:id), :role_id => roles.map(&:id), :old_status_id => status_id, :field_name => field)
+          if rule.present?
+            trackers.each do |tracker|
+              roles.each do |role|
+                WorkflowPermission.create(:role_id => role.id, :tracker_id => tracker.id, :old_status_id => status_id, :field_name => field, :rule => rule)
+              end
+            end
+          end
+        }
       }
-    }
+    end
   end
 
   protected
diff --git a/app/models/workflow_rule.rb b/app/models/workflow_rule.rb
index 829b88a..3d1b75b 100644
--- a/app/models/workflow_rule.rb
+++ b/app/models/workflow_rule.rb
@@ -24,6 +24,7 @@ class WorkflowRule < ActiveRecord::Base
   belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id'
 
   validates_presence_of :role, :tracker, :old_status
+  attr_protected :id
 
   # Copies workflows from source to targets
   def self.copy(source_tracker, source_role, target_trackers, target_roles)
@@ -34,7 +35,7 @@ class WorkflowRule < ActiveRecord::Base
     target_trackers = [target_trackers].flatten.compact
     target_roles = [target_roles].flatten.compact
 
-    target_trackers = Tracker.sorted.all if target_trackers.empty?
+    target_trackers = Tracker.sorted.to_a if target_trackers.empty?
     target_roles = Role.all if target_roles.empty?
 
     target_trackers.each do |target_tracker|
diff --git a/app/models/workflow_transition.rb b/app/models/workflow_transition.rb
index 35d9f26..e88769a 100644
--- a/app/models/workflow_transition.rb
+++ b/app/models/workflow_transition.rb
@@ -21,9 +21,8 @@ class WorkflowTransition < WorkflowRule
   # Returns workflow transitions count by tracker and role
   def self.count_by_tracker_and_role
     counts = connection.select_all("SELECT role_id, tracker_id, count(id) AS c FROM #{table_name} WHERE type = 'WorkflowTransition' GROUP BY role_id, tracker_id")
-    roles = Role.sorted.all
-    trackers = Tracker.sorted.all
-
+    roles    = Role.sorted
+    trackers = Tracker.sorted
     result = []
     trackers.each do |tracker|
       t = []
@@ -33,7 +32,71 @@ class WorkflowTransition < WorkflowRule
       end
       result << [tracker, t]
     end
-
     result
   end
+
+  def self.replace_transitions(trackers, roles, transitions)
+    trackers = Array.wrap trackers
+    roles = Array.wrap roles
+
+    transaction do
+      records = WorkflowTransition.where(:tracker_id => trackers.map(&:id), :role_id => roles.map(&:id)).to_a
+
+      transitions.each do |old_status_id, transitions_by_new_status|
+        transitions_by_new_status.each do |new_status_id, transition_by_rule|
+          transition_by_rule.each do |rule, transition|
+            trackers.each do |tracker|
+              roles.each do |role|
+                w = records.select {|r|
+                  r.old_status_id == old_status_id.to_i &&
+                  r.new_status_id == new_status_id.to_i &&
+                  r.tracker_id == tracker.id &&
+                  r.role_id == role.id &&
+                  !r.destroyed?
+                }
+
+                if rule == 'always'
+                  w = w.select {|r| !r.author && !r.assignee}
+                else
+                  w = w.select {|r| r.author || r.assignee}
+                end
+                if w.size > 1
+                  w[1..-1].each(&:destroy)
+                end
+                w = w.first
+
+                if transition == "1" || transition == true
+                  unless w
+                    w = WorkflowTransition.new(:old_status_id => old_status_id, :new_status_id => new_status_id, :tracker_id => tracker.id, :role_id => role.id)
+                    records << w
+                  end
+                  w.author = true if rule == "author"
+                  w.assignee = true if rule == "assignee"
+                  w.save if w.changed?
+                elsif w
+                  if rule == 'always'
+                    w.destroy
+                  elsif rule == 'author'
+                    if w.assignee
+                      w.author = false
+                      w.save if w.changed?
+                    else
+                      w.destroy
+                    end
+                  elsif rule == 'assignee'
+                    if w.author
+                      w.assignee = false
+                      w.save if w.changed?
+                    else
+                      w.destroy
+                    end
+                  end
+                end
+              end
+            end
+          end
+        end
+      end
+    end
+  end
 end
diff --git a/app/views/groups/_memberships.html.erb b/app/views/groups/_memberships.html.erb
index 777a0df..ec275c5 100644
--- a/app/views/groups/_memberships.html.erb
+++ b/app/views/groups/_memberships.html.erb
@@ -1,5 +1,5 @@
 <% roles = Role.find_all_givable %>
-<% projects = Project.active.all %>
+<% projects = Project.active.to_a %>
 
 <div class="splitcontentleft">
 <% if @group.memberships.any? %>
diff --git a/app/views/groups/index.html.erb b/app/views/groups/index.html.erb
index d48afe9..22c89ef 100644
--- a/app/views/groups/index.html.erb
+++ b/app/views/groups/index.html.erb
@@ -3,7 +3,6 @@
 </div>
 
 <%= title l(:label_group_plural) %>
-
 <% if @groups.any? %>
 <table class="list groups">
   <thead><tr>
@@ -13,9 +12,9 @@
   </tr></thead>
   <tbody>
 <% @groups.each do |group| %>
-  <tr class="<%= cycle 'odd', 'even' %>">
+  <tr id="group-<%= group.id %>" class="<%= cycle 'odd', 'even' %>">
     <td class="name"><%= link_to h(group), edit_group_path(group) %></td>
-    <td><%= group.users.size %></td>
+    <td class="user_count"><%= @user_count_by_group_id[group.id] || 0 %></td>
     <td class="buttons"><%= delete_link group %></td>
   </tr>
 <% end %>
diff --git a/app/views/issues/bulk_edit.html.erb b/app/views/issues/bulk_edit.html.erb
index 2b063f9..b1786dd 100644
--- a/app/views/issues/bulk_edit.html.erb
+++ b/app/views/issues/bulk_edit.html.erb
@@ -185,7 +185,7 @@
 <%= javascript_tag do %>
 $(window).load(function(){
   $(document).on('change', 'input[data-disables]', function(){
-    if ($(this).attr('checked')){
+    if ($(this).prop('checked')){
       $($(this).data('disables')).attr('disabled', true).val('');
     } else {
       $($(this).data('disables')).attr('disabled', false);
diff --git a/app/views/journals/new.js.erb b/app/views/journals/new.js.erb
index 78ec5f3..cd6ab0d 100644
--- a/app/views/journals/new.js.erb
+++ b/app/views/journals/new.js.erb
@@ -3,7 +3,7 @@ $('#issue_notes').val("<%= raw escape_javascript(@content) %>");
   # when quoting a private journal, check the private checkbox
   if @journal && @journal.private_notes? 
 %>
-$('#issue_private_notes').attr('checked', true);
+$('#issue_private_notes').prop('checked', true);
 <% end %>
 
 showAndScrollTo("update", "notes");
diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb
index 99ad13f..0524b22 100644
--- a/app/views/layouts/base.html.erb
+++ b/app/views/layouts/base.html.erb
@@ -7,7 +7,7 @@
 <meta name="keywords" content="issue,bug,tracker" />
 <%= csrf_meta_tag %>
 <%= favicon %>
-<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', 'application', :media => 'all' %>
+<%= stylesheet_link_tag 'jquery/jquery-ui-1.11.0', 'application', :media => 'all' %>
 <%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
 <%= javascript_heads %>
 <%= heads_for_theme %>
diff --git a/app/views/projects/_form.html.erb b/app/views/projects/_form.html.erb
index 0320283..7828bc1 100644
--- a/app/views/projects/_form.html.erb
+++ b/app/views/projects/_form.html.erb
@@ -92,7 +92,7 @@
 <%= javascript_tag do %>
 $(document).ready(function() {
   $('#project_enabled_module_names_issue_tracking').on('change', function(){
-    if ($(this).attr('checked')){
+    if ($(this).prop('checked')){
       $('#project_trackers, #project_issue_custom_fields').show();
     } else {
       $('#project_trackers, #project_issue_custom_fields').hide();
diff --git a/app/views/projects/settings/_members.html.erb b/app/views/projects/settings/_members.html.erb
index ba7bf91..392d1d4 100644
--- a/app/views/projects/settings/_members.html.erb
+++ b/app/views/projects/settings/_members.html.erb
@@ -1,6 +1,6 @@
 <%= error_messages_for 'member' %>
 <% roles = Role.find_all_givable
-   members = @project.member_principals.includes(:member_roles, :roles, :principal).all.sort %>
+   members = @project.member_principals.includes(:member_roles, :roles, :principal).to_a.sort %>
 
 <div class="splitcontentleft">
 <% if members.any? %>
diff --git a/app/views/repositories/_revisions.html.erb b/app/views/repositories/_revisions.html.erb
index 6ef7d21..be86413 100644
--- a/app/views/repositories/_revisions.html.erb
+++ b/app/views/repositories/_revisions.html.erb
@@ -37,8 +37,8 @@ end %>
 <%= content_tag(:td, :class => 'id', :style => id_style) do %>
   <%= link_to_revision(changeset, @repository) %>
 <% end %>
-<td class="checkbox"><%= radio_button_tag('rev', changeset.identifier, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('#cbto-#{line_num+1}').attr('checked',true);") if show_diff && (line_num < revisions.size) %></td>
-<td class="checkbox"><%= radio_button_tag('rev_to', changeset.identifier, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('#cb-#{line_num}').attr('checked')) {$('#cb-#{line_num-1}').attr('checked',true);}") if show_diff && (line_num > 1) %></td>
+<td class="checkbox"><%= radio_button_tag('rev', changeset.identifier, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('#cbto-#{line_num+1}').prop('checked',true);") if show_diff && (line_num < revisions.size) %></td>
+<td class="checkbox"><%= radio_button_tag('rev_to', changeset.identifier, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('#cb-#{line_num}').prop('checked')) {$('#cb-#{line_num-1}').prop('checked',true);}") if show_diff && (line_num > 1) %></td>
 <td class="committed_on"><%= format_time(changeset.committed_on) %></td>
 <td class="author"><%= changeset.author.to_s.truncate(30) %></td>
 <td class="comments"><%= textilizable(truncate_at_line_break(changeset.comments)) %></td>
diff --git a/app/views/search/index.html.erb b/app/views/search/index.html.erb
index 9ea4816..9c88481 100644
--- a/app/views/search/index.html.erb
+++ b/app/views/search/index.html.erb
@@ -56,8 +56,8 @@
 <%= javascript_tag do %>
 $("#search-types a").click(function(e){
   e.preventDefault();
-  $("#search-types input[type=checkbox]").attr('checked', false);
-  $(this).siblings("input[type=checkbox]").attr('checked', true);
+  $("#search-types input[type=checkbox]").prop('checked', false);
+  $(this).siblings("input[type=checkbox]").prop('checked', true);
   if ($("#search-input").val() != "") {
     $("#search-form").submit();
   }
diff --git a/app/views/timelog/_form.html.erb b/app/views/timelog/_form.html.erb
index 3256fea..56f0598 100644
--- a/app/views/timelog/_form.html.erb
+++ b/app/views/timelog/_form.html.erb
@@ -6,7 +6,11 @@
     <% if params[:project_id] || @time_entry.issue %>
       <%= f.hidden_field :project_id %>
     <% else %>
-      <p><%= f.select :project_id, project_tree_options_for_select(Project.allowed_to(:log_time).all, :selected => @time_entry.project), :required => true %></p>
+      <p><%= f.select(:project_id,
+                      project_tree_options_for_select(
+                        Project.allowed_to(:log_time).to_a,
+                        :selected => @time_entry.project),
+                      :required => true) %></p>
     <% end %>
   <% end %>
   <p>
diff --git a/app/views/users/_memberships.html.erb b/app/views/users/_memberships.html.erb
index c0d8051..cd42017 100644
--- a/app/views/users/_memberships.html.erb
+++ b/app/views/users/_memberships.html.erb
@@ -1,5 +1,5 @@
 <% roles = Role.find_all_givable %>
-<% projects = Project.active.all %>
+<% projects = Project.active.to_a %>
 
 <div class="splitcontentleft">
 <% if @user.memberships.any? %>
diff --git a/app/views/wiki/destroy.html.erb b/app/views/wiki/destroy.html.erb
index 08d2cc2..eebe250 100644
--- a/app/views/wiki/destroy.html.erb
+++ b/app/views/wiki/destroy.html.erb
@@ -12,7 +12,7 @@
 <label><%= radio_button_tag 'todo', 'reassign', false %> <%= l(:text_wiki_page_reassign_children) %></label>:
 <%= label_tag "reassign_to_id", l(:description_wiki_subpages_reassign), :class => "hidden-for-sighted" %>
 <%= select_tag 'reassign_to_id', wiki_page_options_for_select(@reassignable_to),
-                                 :onclick => "$('#todo_reassign').attr('checked', true);" %>
+                                 :onclick => "$('#todo_reassign').prop('checked', true);" %>
 <% end %>
 </p>
 </div>
diff --git a/app/views/wiki/edit.html.erb b/app/views/wiki/edit.html.erb
index 3a5a470..40e6b79 100644
--- a/app/views/wiki/edit.html.erb
+++ b/app/views/wiki/edit.html.erb
@@ -23,7 +23,7 @@
       <%= fp.select :parent_id,
                     content_tag('option', '', :value => '') +
                        wiki_page_options_for_select(
-                         @wiki.pages.includes(:parent).all -
+                         @wiki.pages.includes(:parent).to_a -
                          @page.self_and_descendants, @page.parent) %>
     </p>
   <% end %>
diff --git a/app/views/wiki/history.html.erb b/app/views/wiki/history.html.erb
index 56a4478..ebac6d5 100644
--- a/app/views/wiki/history.html.erb
+++ b/app/views/wiki/history.html.erb
@@ -21,7 +21,7 @@
 <% @versions.each do |ver| %>
 <tr class="wiki-page-version <%= cycle("odd", "even") %>">
     <td class="id"><%= link_to h(ver.version), :action => 'show', :id => @page.title, :project_id => @page.project, :version => ver.version %></td>
-    <td class="checkbox"><%= radio_button_tag('version', ver.version, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('#cbto-#{line_num+1}').attr('checked', true);") if show_diff && (line_num < @versions.size) %></td>
+    <td class="checkbox"><%= radio_button_tag('version', ver.version, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('#cbto-#{line_num+1}').prop('checked', true);") if show_diff && (line_num < @versions.size) %></td>
     <td class="checkbox"><%= radio_button_tag('version_from', ver.version, (line_num==2), :id => "cbto-#{line_num}") if show_diff && (line_num > 1) %></td>
     <td class="updated_on"><%= format_time(ver.updated_on) %></td>
     <td class="author"><%= link_to_user ver.author %></td>
diff --git a/app/views/wiki/rename.html.erb b/app/views/wiki/rename.html.erb
index c1a8f33..8531952 100644
--- a/app/views/wiki/rename.html.erb
+++ b/app/views/wiki/rename.html.erb
@@ -13,7 +13,7 @@
 <p><%= f.select :parent_id,
                 content_tag('option', '', :value => '') + 
                   wiki_page_options_for_select(
-                    @wiki.pages.includes(:parent).all - @page.self_and_descendants,
+                    @wiki.pages.includes(:parent).to_a - @page.self_and_descendants,
                     @page.parent),
                 :label => :field_parent_title %></p>
 </div>
diff --git a/app/views/workflows/_form.html.erb b/app/views/workflows/_form.html.erb
index 19d94d6..9c5ef62 100644
--- a/app/views/workflows/_form.html.erb
+++ b/app/views/workflows/_form.html.erb
@@ -1,4 +1,4 @@
-<table class="list transitions transitions-<%= name %>">
+<table class="list workflows transitions transitions-<%= name %>">
 <thead>
   <tr>
     <th>
@@ -31,8 +31,7 @@
     <% for new_status in @statuses -%>
     <% checked = workflows.detect {|w| w.old_status_id == old_status.id && w.new_status_id == new_status.id} %>
     <td class="<%= checked ? 'enabled' : '' %>">
-      <%= check_box_tag "issue_status[#{ old_status.id }][#{new_status.id}][]", name, checked,
-            :class => "old-status-#{old_status.id} new-status-#{new_status.id}" %>
+      <%= transition_tag workflows, old_status, new_status, name %>
     </td>
     <% end -%>
   </tr>
diff --git a/app/views/workflows/edit.html.erb b/app/views/workflows/edit.html.erb
index 8c02653..19b4093 100644
--- a/app/views/workflows/edit.html.erb
+++ b/app/views/workflows/edit.html.erb
@@ -4,8 +4,8 @@
 
 <div class="tabs">
   <ul>
-    <li><%= link_to l(:label_status_transitions), {:action => 'edit', :role_id => @role, :tracker_id => @tracker}, :class => 'selected' %></li>
-    <li><%= link_to l(:label_fields_permissions), {:action => 'permissions', :role_id => @role, :tracker_id => @tracker} %></li>
+    <li><%= link_to l(:label_status_transitions), workflows_edit_path(:role_id => @roles, :tracker_id => @trackers), :class => 'selected' %></li>
+    <li><%= link_to l(:label_fields_permissions), workflows_permissions_path(:role_id => @roles, :tracker_id => @trackers) %></li>
   </ul>
 </div>
 
@@ -14,10 +14,14 @@
 <%= form_tag({}, :method => 'get') do %>
 <p>
   <label><%=l(:label_role)%>:
-  <%= select_tag 'role_id', options_from_collection_for_select(@roles, "id", "name", @role && @role.id) %></label>
+  <%= options_for_workflow_select 'role_id[]', Role.sorted, @roles, :id => 'role_id', :class => 'expandable' %>
+  </label>
+  <a href="#" data-expands="#role_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
 
   <label><%=l(:label_tracker)%>:
-  <%= select_tag 'tracker_id', options_from_collection_for_select(@trackers, "id", "name", @tracker && @tracker.id) %></label>
+  <%= options_for_workflow_select 'tracker_id[]', Tracker.sorted, @trackers, :id => 'tracker_id', :class => 'expandable' %>
+  </label>
+  <a href="#" data-expands="#tracker_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
 
   <%= submit_tag l(:button_edit), :name => nil %>
 
@@ -27,10 +31,10 @@
 </p>
 <% end %>
 
-<% if @tracker && @role && @statuses.any? %>
+<% if @trackers && @roles && @statuses.any? %>
   <%= form_tag({}, :id => 'workflow_form' ) do %>
-    <%= hidden_field_tag 'tracker_id', @tracker.id %>
-    <%= hidden_field_tag 'role_id', @role.id %>
+    <%= @trackers.map {|tracker| hidden_field_tag 'tracker_id[]', tracker.id}.join.html_safe %>
+    <%= @roles.map {|role| hidden_field_tag 'role_id[]', role.id}.join.html_safe %>
     <%= hidden_field_tag 'used_statuses_only', params[:used_statuses_only] %>
     <div class="autoscroll">
       <%= render :partial => 'form', :locals => {:name => 'always', :workflows => @workflows['always']} %>
@@ -54,3 +58,18 @@
     <%= submit_tag l(:button_save) %>
   <% end %>
 <% end %>
+
+<%= javascript_tag do %>
+$("a[data-expands]").click(function(e){
+  e.preventDefault();
+  var target = $($(this).attr("data-expands"));
+  if (target.attr("multiple")) {
+    target.attr("multiple", false);
+    target.find("option[value=all]").show();
+  } else {
+    target.attr("multiple", true);
+    target.find("option[value=all]").attr("selected", false).hide();
+  }
+});
+
+<% end %>
diff --git a/app/views/workflows/permissions.html.erb b/app/views/workflows/permissions.html.erb
index 11212e6..54b8304 100644
--- a/app/views/workflows/permissions.html.erb
+++ b/app/views/workflows/permissions.html.erb
@@ -4,8 +4,8 @@
 
 <div class="tabs">
   <ul>
-    <li><%= link_to l(:label_status_transitions), {:action => 'edit', :role_id => @role, :tracker_id => @tracker} %></li>
-    <li><%= link_to l(:label_fields_permissions), {:action => 'permissions', :role_id => @role, :tracker_id => @tracker}, :class => 'selected' %></li>
+    <li><%= link_to l(:label_status_transitions), workflows_edit_path(:role_id => @roles, :tracker_id => @trackers) %></li>
+    <li><%= link_to l(:label_fields_permissions), workflows_permissions_path(:role_id => @roles, :tracker_id => @trackers), :class => 'selected' %></li>
   </ul>
 </div>
 
@@ -14,10 +14,14 @@
 <%= form_tag({}, :method => 'get') do %>
 <p>
   <label><%=l(:label_role)%>:
-  <%= select_tag 'role_id', options_from_collection_for_select(@roles, "id", "name", @role && @role.id) %></label>
+  <%= options_for_workflow_select 'role_id[]', Role.sorted, @roles, :id => 'role_id', :class => 'expandable' %>
+  </label>
+  <a href="#" data-expands="#role_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
 
   <label><%=l(:label_tracker)%>:
-  <%= select_tag 'tracker_id', options_from_collection_for_select(@trackers, "id", "name", @tracker && @tracker.id) %></label>
+  <%= options_for_workflow_select 'tracker_id[]', Tracker.sorted, @trackers, :id => 'tracker_id', :class => 'expandable' %>
+  </label>
+  <a href="#" data-expands="#tracker_id"><%= image_tag 'bullet_toggle_plus.png' %></a>
 
   <%= submit_tag l(:button_edit), :name => nil %>
 
@@ -26,13 +30,13 @@
 </p>
 <% end %>
 
-<% if @tracker && @role && @statuses.any? %>
+<% if @trackers && @roles && @statuses.any? %>
   <%= form_tag({}, :id => 'workflow_form' ) do %>
-    <%= hidden_field_tag 'tracker_id', @tracker.id %>
-    <%= hidden_field_tag 'role_id', @role.id %>
+    <%= @trackers.map {|tracker| hidden_field_tag 'tracker_id[]', tracker.id}.join.html_safe %>
+    <%= @roles.map {|role| hidden_field_tag 'role_id[]', role.id}.join.html_safe %>
     <%= hidden_field_tag 'used_statuses_only', params[:used_statuses_only] %>
     <div class="autoscroll">
-    <table class="list fields_permissions">
+    <table class="list workflows fields_permissions">
     <thead>
       <tr>
         <th>
@@ -62,7 +66,7 @@
         </td>
         <% for status in @statuses -%>
         <td class="<%= @permissions[status.id][field] %>">
-          <%= field_permission_tag(@permissions, status, field, @role) %>
+          <%= field_permission_tag(@permissions, status, field, @roles) %>
           <% unless status == @statuses.last %><a href="#" class="repeat-value">»</a><% end %>
         </td>
         <% end -%>
@@ -82,7 +86,7 @@
           </td>
           <% for status in @statuses -%>
           <td class="<%= @permissions[status.id][field.id.to_s] %>">
-            <%= field_permission_tag(@permissions, status, field, @role) %>
+            <%= field_permission_tag(@permissions, status, field, @roles) %>
             <% unless status == @statuses.last %><a href="#" class="repeat-value">»</a><% end %>
           </td>
           <% end -%>
@@ -103,4 +107,17 @@ $("a.repeat-value").click(function(e){
   var selected = td.find("select").find(":selected").val();
   td.nextAll('td').find("select").val(selected);
 });
+
+$("a[data-expands]").click(function(e){
+  e.preventDefault();
+  var target = $($(this).attr("data-expands"));
+  if (target.attr("multiple")) {
+    target.attr("multiple", false);
+    target.find("option[value=all]").show();
+  } else {
+    target.attr("multiple", true);
+    target.find("option[value=all]").attr("selected", false).hide();
+  }
+});
+
 <% end %>
diff --git a/script/about b/bin/about
similarity index 100%
copy from script/about
copy to bin/about
diff --git a/bin/bundle b/bin/bundle
new file mode 100644
index 0000000..e3c2f62
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby.exe
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/rails b/bin/rails
new file mode 100644
index 0000000..b9f8787
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby.exe
+APP_PATH = File.expand_path('../../config/application',  __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
diff --git a/bin/rake b/bin/rake
new file mode 100644
index 0000000..f6ed5a2
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby.exe
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
diff --git a/config/application.rb b/config/application.rb
index 58d949a..b05c528 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -2,12 +2,7 @@ require File.expand_path('../boot', __FILE__)
 
 require 'rails/all'
 
-if defined?(Bundler)
-  # If you precompile assets before deploying to production, use this line
-  Bundler.require(*Rails.groups(:assets => %w(development test)))
-  # If you want your assets lazily compiled in production, use this line
-  # Bundler.require(:default, :assets, Rails.env)
-end
+Bundler.require(*Rails.groups)
 
 module RedmineApp
   class Application < Rails::Application
@@ -33,7 +28,7 @@ module RedmineApp
     # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
     # config.i18n.default_locale = :de
 
-    I18n.enforce_available_locales = false
+    I18n.enforce_available_locales = true
 
     # Configure the default encoding used in templates for Ruby 1.9.
     config.encoding = "utf-8"
diff --git a/config/boot.rb b/config/boot.rb
index 4489e58..3596736 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,5 +1,3 @@
-require 'rubygems'
-
 # Set up gems listed in the Gemfile.
 ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
 
diff --git a/config/database.yml.example b/config/database.yml.example
index 5bcf17b..57bc516 100644
--- a/config/database.yml.example
+++ b/config/database.yml.example
@@ -1,5 +1,4 @@
-# Default setup is given for MySQL with ruby1.9. If you're running Redmine
-# with MySQL and ruby1.8, replace the adapter name with `mysql`.
+# Default setup is given for MySQL with ruby1.9.
 # Examples for PostgreSQL, SQLite3 and SQL Server can be found at the end.
 # Line indentation must be 2 spaces (no tabs).
 
diff --git a/config/environment.rb b/config/environment.rb
index 1d9a396..705e4ec 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,4 +1,4 @@
-# Load the rails application
+# Load the Rails application
 require File.expand_path('../application', __FILE__)
 
 # Make sure there's no plugin in vendor/plugin before starting
@@ -10,5 +10,5 @@ if Dir.glob(File.join(vendor_plugins_dir, "*")).any?
   exit 1
 end
 
-# Initialize the rails application
-RedmineApp::Application.initialize!
+# Initialize the Rails application
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
index bd66a78..f7b15e1 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -1,19 +1,21 @@
-# Settings specified here will take precedence over those in config/application.rb
-RedmineApp::Application.configure do
+Rails.application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
   # In the development environment your application's code is reloaded on
   # every request.  This slows down response time but is perfect for development
   # since you don't have to restart the webserver when you make code changes.
-  config.cache_classes     = false
+  config.cache_classes = false
 
-  # Log error messages when you accidentally call methods on nil.
-  config.whiny_nils        = true
+  # Do not eager load code on boot.
+  config.eager_load = false
 
   # Show full error reports and disable caching
-  #config.action_controller.consider_all_requests_local = true
-  config.action_controller.perform_caching             = false
+  config.consider_all_requests_local = true
+  config.action_controller.perform_caching = false
 
-  # Don't care if the mailer can't send
+  # Disable delivery errors
   config.action_mailer.raise_delivery_errors = false
 
+  # Print deprecation notices to stderr and the Rails logger.
   config.active_support.deprecation = [:stderr, :log]
 end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index ecb4cf9..85cd389 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,33 +1,25 @@
-# Settings specified here will take precedence over those in config/application.rb
-RedmineApp::Application.configure do
-  # The production environment is meant for finished, "live" apps.
-  # Code is not reloaded between requests
+Rails.application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # Code is not reloaded between requests.
   config.cache_classes = true
 
-  #####
-  # Customize the default logger
-  # http://www.ruby-doc.org/stdlib-1.8.7/libdoc/logger/rdoc/Logger.html
-  #
-  # Use a different logger for distributed setups
-  # config.logger        = SyslogLogger.new
-  #
-  # Rotate logs bigger than 1MB, keeps no more than 7 rotated logs around.
-  # When setting a new Logger, make sure to set it's log level too.
-  #
-  # config.logger = Logger.new(config.log_path, 7, 1048576)
-  # config.logger.level = Logger::INFO
+  # Eager load code on boot. This eager loads most of Rails and
+  # your application in memory, allowing both threaded web servers
+  # and those relying on copy on write to perform better.
+  # Rake tasks automatically ignore this option for performance.
+  config.eager_load = true
 
-  # Full error reports are disabled and caching is turned on
+  # Full error reports are disabled and caching is turned on.
+  config.consider_all_requests_local = false
   config.action_controller.perform_caching = true
 
-  # Enable serving of images, stylesheets, and javascripts from an asset server
-  # config.action_controller.asset_host                  = "http://assets.example.com"
-
-  # Disable delivery errors if you bad email addresses should just be ignored
+  # Disable delivery errors
   config.action_mailer.raise_delivery_errors = false
 
   # No email in production log
   config.action_mailer.logger = nil
 
+  # Print deprecation notices to the Rails logger.
   config.active_support.deprecation = :log
 end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index f3d0ee9..2499104 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,16 +1,19 @@
-# Settings specified here will take precedence over those in config/application.rb
-RedmineApp::Application.configure do
+Rails.application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
   # The test environment is used exclusively to run your application's
   # test suite.  You never need to work with it otherwise.  Remember that
   # your test database is "scratch space" for the test suite and is wiped
   # and recreated between test runs.  Don't rely on the data there!
   config.cache_classes = true
 
-  # Log error messages when you accidentally call methods on nil.
-  config.whiny_nils = true
+  # Do not eager load code on boot. This avoids loading your whole application
+  # just for the purpose of running a single test. If you are using a tool that
+  # preloads Rails for running tests, you may have to set it to true.
+  config.eager_load = false
 
   # Show full error reports and disable caching
-  #config.action_controller.consider_all_requests_local = true
+  config.consider_all_requests_local = true
   config.action_controller.perform_caching = false
 
   config.action_mailer.perform_deliveries = true
@@ -20,10 +23,10 @@ RedmineApp::Application.configure do
   # ActionMailer::Base.deliveries array.
   config.action_mailer.delivery_method = :test
 
-  # Skip protect_from_forgery in requests
-  # http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
+  # Disable request forgery protection in test environment.
   config.action_controller.allow_forgery_protection = false
 
+  # Print deprecation notices to stderr and the Rails logger.
   config.active_support.deprecation = [:stderr, :log]
 
   config.secret_token = 'a secret token for running the tests'
diff --git a/config/environments/test_pgsql.rb b/config/environments/test_pgsql.rb
index 45cb09b..258914d 100644
--- a/config/environments/test_pgsql.rb
+++ b/config/environments/test_pgsql.rb
@@ -1 +1,2 @@
+# Same as test.rb
 instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb'))
diff --git a/config/environments/test_sqlite3.rb b/config/environments/test_sqlite3.rb
index 45cb09b..258914d 100644
--- a/config/environments/test_sqlite3.rb
+++ b/config/environments/test_sqlite3.rb
@@ -1 +1,2 @@
+# Same as test.rb
 instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb'))
diff --git a/config/initializers/10-patches.rb b/config/initializers/10-patches.rb
index 7247d52..ff74c30 100644
--- a/config/initializers/10-patches.rb
+++ b/config/initializers/10-patches.rb
@@ -54,56 +54,23 @@ module ActionView
   end
 end
 
-# Do not HTML escape text templates
-module ActionView
-  class Template
-    module Handlers
-      class ERB
-        def call(template)
-          if template.source.encoding_aware?
-            # First, convert to BINARY, so in case the encoding is
-            # wrong, we can still find an encoding tag
-            # (<%# encoding %>) inside the String using a regular
-            # expression
-            template_source = template.source.dup.force_encoding("BINARY")
-
-            erb = template_source.gsub(ENCODING_TAG, '')
-            encoding = $2
-
-            erb.force_encoding valid_encoding(template.source.dup, encoding)
-
-            # Always make sure we return a String in the default_internal
-            erb.encode!
-          else
-            erb = template.source.dup
-          end
-
-          self.class.erb_implementation.new(
-            erb,
-            :trim => (self.class.erb_trim_mode == "-"),
-            :escape => template.identifier =~ /\.text/ # only escape HTML templates
-          ).src
-        end
-      end
-    end
-  end
-end
-
 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe }
 
 # HTML5: <option value=""></option> is invalid, use <option value=""> </option> instead
 module ActionView
   module Helpers
-    class InstanceTag
-      private
-      def add_options_with_non_empty_blank_option(option_tags, options, value = nil)
-        if options[:include_blank] == true
-          options = options.dup
-          options[:include_blank] = ' '.html_safe
+    module Tags
+      class Base
+        private
+        def add_options_with_non_empty_blank_option(option_tags, options, value = nil)
+          if options[:include_blank] == true
+            options = options.dup
+            options[:include_blank] = ' '.html_safe
+          end
+          add_options_without_non_empty_blank_option(option_tags, options, value)
         end
-        add_options_without_non_empty_blank_option(option_tags, options, value)
+        alias_method_chain :add_options, :non_empty_blank_option
       end
-      alias_method_chain :add_options, :non_empty_blank_option
     end
 
     module FormTagHelper
@@ -227,8 +194,6 @@ if Rails::VERSION::MAJOR < 4 && RUBY_VERSION >= "2.1"
   end
 end
 
-require 'awesome_nested_set/version'
-
 module CollectiveIdea
   module Acts
     module NestedSet
@@ -237,23 +202,6 @@ module CollectiveIdea
           new_record? || leaf_without_new_record?
         end
         alias_method_chain :leaf?, :new_record
-        # Reload is needed because children may have updated
-        # their parent (self) during deletion.
-        if ::AwesomeNestedSet::VERSION > "2.1.6"
-          module Prunable
-            def destroy_descendants_with_reload
-              destroy_descendants_without_reload
-              reload
-            end
-            alias_method_chain :destroy_descendants, :reload
-          end
-        else
-          def destroy_descendants_with_reload
-            destroy_descendants_without_reload
-            reload
-          end
-          alias_method_chain :destroy_descendants, :reload
-        end
       end
     end
   end
diff --git a/config/initializers/30-redmine.rb b/config/initializers/30-redmine.rb
index b0cc1f7..a736902 100644
--- a/config/initializers/30-redmine.rb
+++ b/config/initializers/30-redmine.rb
@@ -1,5 +1,7 @@
 I18n.default_locale = 'en'
 I18n.backend = Redmine::I18n::Backend.new
+# Forces I18n to load available locales from the backend
+I18n.config.available_locales = nil
 
 require 'redmine'
 
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index 04668d0..3525a33 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -1112,6 +1112,7 @@ ar:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/az.yml b/config/locales/az.yml
index c4881f0..81fdf14 100644
--- a/config/locales/az.yml
+++ b/config/locales/az.yml
@@ -1209,6 +1209,7 @@ az:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index 9400e23..ef311a2 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -511,6 +511,7 @@ bg:
   label_issue_updated: Обновена задача
   label_issue_note_added: Добавена бележка
   label_issue_status_updated: Обновено състояние
+  label_issue_assigned_to_updated: Задачата е с назначен нов изпълнител
   label_issue_priority_updated: Обновен приоритет
   label_document: Документ
   label_document_new: Нов документ
diff --git a/config/locales/bs.yml b/config/locales/bs.yml
index 80b7b5e..879ae9e 100644
--- a/config/locales/bs.yml
+++ b/config/locales/bs.yml
@@ -1125,6 +1125,7 @@ bs:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 2f9b512..7b8cd58 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -1114,6 +1114,7 @@ ca:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 2e902c3..95c2144 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -1114,6 +1114,7 @@ cs:
   setting_force_default_language_for_loggedin: Vynutit výchozí jazyk pro přihlášené uživatele
     users
   label_custom_field_select_type: Vybrat typ objektu, ke kterému bude přiřazeno uživatelské pole
+  label_issue_assigned_to_updated: Přiřazený uživatel aktualizován
   label_check_for_updates: Zkontroluj aktualizace
   label_latest_compatible_version: Poslední kompatibilní verze
   label_unknown_plugin: Nezámý plugin
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 02d10f0..788b326 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -1129,6 +1129,7 @@ da:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/de.yml b/config/locales/de.yml
index d63d78a..eac742f 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -569,6 +569,7 @@ de:
   label_internal: Intern
   label_issue: Ticket
   label_issue_added: Ticket hinzugefügt
+  label_issue_assigned_to_updated: Bearbeiter aktualisiert
   label_issue_category: Ticket-Kategorie
   label_issue_category_new: Neue Kategorie
   label_issue_category_plural: Ticket-Kategorien
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 785eb8d..fce79df 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -1112,6 +1112,7 @@ el:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml
index a257d9a..0107706 100644
--- a/config/locales/en-GB.yml
+++ b/config/locales/en-GB.yml
@@ -1114,6 +1114,7 @@ en-GB:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/en.yml b/config/locales/en.yml
index e28b8e7..abcd3f9 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -508,6 +508,7 @@ en:
   label_issue_updated: Issue updated
   label_issue_note_added: Note added
   label_issue_status_updated: Status updated
+  label_issue_assigned_to_updated: Assignee updated
   label_issue_priority_updated: Priority updated
   label_document: Document
   label_document_new: New document
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 804f61e..8cedd16 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -1145,6 +1145,7 @@ es:
   setting_force_default_language_for_anonymous: Forzar lenguaje por defecto a usuarios anónimos
   setting_force_default_language_for_loggedin: Forzar lenguaje por defecto para usuarios identificados
   label_custom_field_select_type: Seleccione el tipo de objeto al que unir el campo personalizado
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/et.yml b/config/locales/et.yml
index 56ecd78..c613c74 100644
--- a/config/locales/et.yml
+++ b/config/locales/et.yml
@@ -1125,6 +1125,7 @@ et:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index 9300814..d50e65a 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -1113,6 +1113,7 @@ eu:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index faff21f..fd11438 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -10,8 +10,8 @@ fa:
       short: "%b %d"
       long: "%B %d, %Y"
 
-    day_names: [یک‌شنبه, دوشنبه, سه‌شنبه, چهارشنبه, پنج‌شنبه, آدینه, شنبه]
-    abbr_day_names: [یک, دو, سه, چهار, پنج, آدینه, شنبه]
+    day_names: [یک‌شنبه, دوشنبه, سه‌شنبه, چهارشنبه, پنج‌شنبه, جمعه, شنبه]
+    abbr_day_names: [یک, دو, سه, چهار, پنج, جمعه, شنبه]
 
     # Don't forget the nil at the beginning; there's no such thing as a 0th month
     month_names: [~, ژانویه, فوریه, مارس, آوریل, مه, ژوئن, ژوئیه, اوت, سپتامبر, اکتبر, نوامبر, دسامبر]
@@ -128,7 +128,7 @@ fa:
         greater_than_start_date: "باید از تاریخ آغاز بزرگتر باشد"
         not_same_project: "به همان پروژه وابسته نیست"
         circular_dependency: "این وابستگی یک وابستگی دایره وار خواهد ساخت"
-        cant_link_an_issue_with_a_descendant: "یک پیامد نمی‌تواند به یکی از زیر کارهایش پیوند بخورد"
+        cant_link_an_issue_with_a_descendant: "یک مورد نمی‌تواند به یکی از زیر کارهایش پیوند بخورد"
         earlier_than_minimum_start_date: "cannot be earlier than %{date} because of preceding issues"
 
   actionview_instancetag_blank_option: گزینش کنید
@@ -151,46 +151,46 @@ fa:
   notice_account_register_done: حساب ساخته شد. برای فعال نمودن آن، روی پیوندی که به شما ایمیل شده کلیک کنید.
   notice_account_unknown_email: کاربر شناخته نشد.
   notice_can_t_change_password:  این حساب یک روش شناسایی بیرونی را به کار گرفته است. گذرواژه را نمی‌توان جایگزین کرد.
-  notice_account_lost_email_sent: یک ایمیل با راهنمایی درباره گزینش گذرواژه تازه برای شما فرستاده شد.
+  notice_account_lost_email_sent: یک ایمیل با راهنمایی درباره گزینش گذرواژه جدید برای شما فرستاده شد.
   notice_account_activated: حساب شما فعال شده است. اکنون می‌توانید وارد شوید.
   notice_successful_create: با موفقیت ساخته شد.
   notice_successful_update: با موفقیت بروز شد.
   notice_successful_delete: با موفقیت برداشته شد.
   notice_successful_connection: با موفقیت متصل شد.
-  notice_file_not_found: برگه درخواستی شما در دسترس نیست یا پاک شده است.
+  notice_file_not_found: صفحه درخواستی شما در دسترس نیست یا پاک شده است.
   notice_locking_conflict: داده‌ها را کاربر دیگری بروز کرده است.
-  notice_not_authorized: شما به این برگه دسترسی ندارید.
+  notice_not_authorized: شما به این صفحه دسترسی ندارید.
   notice_not_authorized_archived_project: پروژه درخواستی شما بایگانی شده است.
   notice_email_sent: "یک ایمیل به %{value} فرستاده شد."
   notice_email_error: "یک ایراد در فرستادن ایمیل پیش آمد (%{value})."
   notice_feeds_access_key_reseted: کلید دسترسی Atom شما بازنشانی شد.
   notice_api_access_key_reseted: کلید دسترسی API شما بازنشانی شد.
-  notice_failed_to_save_issues: "ذخیره سازی %{count} پیامد از %{total} پیامد گزینش شده شکست خورد: %{ids}."
-  notice_failed_to_save_members: "ذخیره سازی اعضا شکست خورد: %{errors}."
-  notice_no_issue_selected: "هیچ پیامدی برگزیده نشده است! پیامدهایی که می‌خواهید ویرایش کنید را برگزینید."
-  notice_account_pending: "حساب شما ساخته شد و اکنون چشم به راه روادید سرپرست است."
+  notice_failed_to_save_issues: "ذخیره سازی %{count} مورد از %{total} مورد گزینش شده شکست خورد: %{ids}."
+  notice_failed_to_save_members: "ذخیره سازی همکاران شکست خورد: %{errors}."
+  notice_no_issue_selected: "هیچ موردی انتخاب نشده است! موردهایی که می‌خواهید ویرایش کنید را انتخاب کنید."
+  notice_account_pending: "حساب شما ساخته شد و اکنون منتظر تایید مدیر سایت است."
   notice_default_data_loaded: پیکربندی پیش‌گزیده با موفقیت بار شد.
   notice_unable_delete_version: نگارش را نمی‌توان پاک کرد.
   notice_unable_delete_time_entry: زمان گزارش شده را نمی‌توان پاک کرد.
-  notice_issue_done_ratios_updated: اندازه انجام شده پیامد بروز شد.
+  notice_issue_done_ratios_updated: اندازه انجام شده مورد بروز شد.
   notice_gantt_chart_truncated: "نمودار بریده شد چون از بیشترین شماری که می‌توان نشان داد بزگتر است (%{max})."
 
   error_can_t_load_default_data: "پیکربندی پیش‌گزیده نمی‌تواند بار شود: %{value}"
-  error_scm_not_found: "بخش یا نگارش در انباره پیدا نشد."
-  error_scm_command_failed: "ایرادی در دسترسی به انباره پیش آمد: %{value}"
+  error_scm_not_found: "بخش یا نگارش در بایگانی پیدا نشد."
+  error_scm_command_failed: "ایرادی در دسترسی به بایگانی پیش آمد: %{value}"
   error_scm_annotate: "بخش پیدا نشد یا نمی‌توان برای آن یادداشت نوشت."
-  error_issue_not_found_in_project: 'پیامد پیدا نشد یا به این پروژه وابسته نیست.'
-  error_no_tracker_in_project: 'هیچ پیگردی به این پروژه پیوسته نشده است. پیکربندی پروژه را بررسی کنید.'
-  error_no_default_issue_status: 'هیچ وضعیت پیامد پیش‌گزیده‌ای مشخص نشده است. پیکربندی را بررسی کنید (به «پیکربندی -> وضعیت‌های پیامد» بروید).'
+  error_issue_not_found_in_project: 'مورد پیدا نشد یا به این پروژه وابسته نیست.'
+  error_no_tracker_in_project: 'هیچ ردیابی به این پروژه پیوسته نشده است. پیکربندی پروژه را بررسی کنید.'
+  error_no_default_issue_status: 'هیچ وضعیت مورد پیش‌گزیده‌ای مشخص نشده است. پیکربندی را بررسی کنید (به «پیکربندی -> وضعیت‌های مورد» بروید).'
   error_can_not_delete_custom_field: فیلد سفارشی را نمی‌توان پاک کرد.
-  error_can_not_delete_tracker: "این پیگرد دارای پیامد است و نمی‌توان آن را پاک کرد."
+  error_can_not_delete_tracker: "این ردیاب دارای مورد است و نمی‌توان آن را پاک کرد."
   error_can_not_remove_role: "این نقش به کار گرفته شده است و نمی‌توان آن را پاک کرد."
-  error_can_not_reopen_issue_on_closed_version: 'یک پیامد که به یک نگارش بسته شده وابسته است را نمی‌توان باز کرد.'
+  error_can_not_reopen_issue_on_closed_version: 'یک مورد که به یک نگارش بسته شده وابسته است را نمی‌توان باز کرد.'
   error_can_not_archive_project: این پروژه را نمی‌توان بایگانی کرد.
-  error_issue_done_ratios_not_updated: "اندازه انجام شده پیامد بروز نشد."
-  error_workflow_copy_source: 'یک پیگرد یا نقش منبع را برگزینید.'
-  error_workflow_copy_target: 'پیگردها یا نقش‌های مقصد را برگزینید.'
-  error_unable_delete_issue_status: 'وضعیت پیامد را نمی‌توان پاک کرد.'
+  error_issue_done_ratios_not_updated: "اندازه انجام شده مورد بروز نشد."
+  error_workflow_copy_source: 'یک ردیاب یا نقش منبع را برگزینید.'
+  error_workflow_copy_target: 'ردیابها یا نقش‌های مقصد را برگزینید.'
+  error_unable_delete_issue_status: 'وضعیت مورد را نمی‌توان پاک کرد.'
   error_unable_to_connect: "نمی‌توان متصل شد (%{value})"
   warning_attachments_not_saved: "%{count} پرونده ذخیره نشد."
 
@@ -201,17 +201,16 @@ fa:
   mail_body_account_information_external: "شما می‌توانید حساب %{value} خود را برای ورود به کار برید."
   mail_body_account_information: داده‌های حساب شما
   mail_subject_account_activation_request: "درخواست فعالسازی حساب %{value}"
-  mail_body_account_activation_request: "یک کاربر تازه (%{value}) نامنویسی کرده است. این حساب چشم به راه روادید شماست:"
-  mail_subject_reminder: "زمان رسیدگی به %{count} پیامد در %{days} روز آینده سر می‌رسد"
-  mail_body_reminder: "زمان رسیدگی به %{count} پیامد که به شما واگذار شده است، در %{days} روز آینده سر می‌رسد:"
-  mail_subject_wiki_content_added: "برگه ویکی «%{id}» افزوده شد"
-  mail_body_wiki_content_added: "برگه ویکی «%{id}» به دست %{author} افزوده شد."
-  mail_subject_wiki_content_updated: "برگه ویکی «%{id}» بروز شد"
-  mail_body_wiki_content_updated: "برگه ویکی «%{id}» به دست %{author} بروز شد."
-
+  mail_body_account_activation_request: "یک کاربر جدید (%{value}) نامنویسی کرده است. این حساب منتظر تایید شماست:"
+  mail_subject_reminder: "زمان رسیدگی به %{count} مورد در %{days} روز آینده سر می‌رسد"
+  mail_body_reminder: "زمان رسیدگی به %{count} مورد که به شما واگذار شده است، در %{days} روز آینده سر می‌رسد:"
+  mail_subject_wiki_content_added: "صفحه ویکی «%{id}» افزوده شد"
+  mail_body_wiki_content_added: "صفحه ویکی «%{id}» به دست %{author} افزوده شد."
+  mail_subject_wiki_content_updated: "صفحه ویکی «%{id}» بروز شد"
+  mail_body_wiki_content_updated: "صفحه ویکی «%{id}» به دست %{author} بروز شد."
 
   field_name: نام
-  field_description: یادداشت
+  field_description: توضیحات
   field_summary: خلاصه
   field_is_required: الزامی
   field_firstname: نام کوچک
@@ -230,43 +229,43 @@ fa:
   field_min_length: کمترین اندازه
   field_max_length: بیشترین اندازه
   field_value: مقدار
-  field_category: دسته
+  field_category: دسته بندی
   field_title: عنوان
   field_project: پروژه
-  field_issue: پیامد
+  field_issue: مورد
   field_status: وضعیت
   field_notes: یادداشت
-  field_is_closed: پیامد بسته شده
+  field_is_closed: مورد بسته شده
   field_is_default: مقدار پیش‌گزیده
-  field_tracker: پیگرد
+  field_tracker: ردیاب
   field_subject: موضوع
   field_due_date: زمان سررسید
   field_assigned_to: واگذار شده به
-  field_priority: برتری
+  field_priority: اولویت
   field_fixed_version: نگارش هدف
   field_user: کاربر
   field_principal: دستور دهنده
   field_role: نقش
-  field_homepage: برگه خانه
+  field_homepage: صفحه اصلی
   field_is_public: همگانی
   field_parent: پروژه پدر
-  field_is_in_roadmap: این پیامدها در چشم‌انداز نشان داده شوند
-  field_login: ورود
+  field_is_in_roadmap: این موردها در نقشه راه نشان داده شوند
+  field_login: کد پرسنلی
   field_mail_notification: آگاه سازی‌های ایمیلی
-  field_admin: سرپرست
+  field_admin: مدیر سایت
   field_last_login_on: آخرین ورود
   field_language: زبان
   field_effective_date: تاریخ
   field_password: گذرواژه
-  field_new_password: گذرواژه تازه
-  field_password_confirmation: بررسی گذرواژه
+  field_new_password: گذرواژه جدید
+  field_password_confirmation: تکرار گذرواژه
   field_version: نگارش
   field_type: گونه
   field_host: میزبان
   field_port: درگاه
   field_account: حساب
   field_base_dn: DN پایه
-  field_attr_login: نشانه ورود
+  field_attr_login: نشانه کد پرسنلی
   field_attr_firstname: نشانه نام کوچک
   field_attr_lastname: نشانه نام خانوادگی
   field_attr_mail: نشانه ایمیل
@@ -275,42 +274,42 @@ fa:
   field_done_ratio: ٪ انجام شده
   field_auth_source: روش شناسایی
   field_hide_mail: ایمیل من پنهان شود
-  field_comments: دیدگاه
+  field_comments: نظر
   field_url: نشانی
-  field_start_page: برگه آغاز
+  field_start_page: صفحه آغاز
   field_subproject: زیر پروژه
   field_hours: ساعت‌
   field_activity: گزارش
   field_spent_on: در تاریخ
   field_identifier: شناسه
   field_is_filter: پالایش پذیر
-  field_issue_to: پیامد وابسته
+  field_issue_to: مورد وابسته
   field_delay: دیرکرد
-  field_assignable: پیامدها می‌توانند به این نقش واگذار شوند
-  field_redirect_existing_links: پیوندهای پیشین  به پیوند تازه راهنمایی شوند
+  field_assignable: موردها می‌توانند به این نقش واگذار شوند
+  field_redirect_existing_links: پیوندهای پیشین  به پیوند جدید راهنمایی شوند
   field_estimated_hours: زمان برآورد شده
   field_column_names: ستون‌ها
   field_time_entries: زمان نوشتن
   field_time_zone: پهنه زمانی
   field_searchable: جستجو پذیر
   field_default_value: مقدار پیش‌گزیده
-  field_comments_sorting: نمایش دیدگاه‌ها
-  field_parent_title: برگه پدر
+  field_comments_sorting: نمایش نظر‌ها
+  field_parent_title: صفحه پدر
   field_editable: ویرایش پذیر
   field_watcher: دیده‌بان
   field_identity_url: نشانی OpenID
   field_content: محتوا
   field_group_by: دسته بندی با
   field_sharing: اشتراک گذاری
-  field_parent_issue: کار پدر
-  field_member_of_group: "دسته واگذار شونده"
+  field_parent_issue: فعاليت یا مورد مافوق
+  field_member_of_group: "همکار گروه واگذار شونده"
   field_assigned_to_role: "نقش واگذار شونده"
   field_text: فیلد متنی
   field_visible: آشکار
 
   setting_app_title: نام برنامه
   setting_app_subtitle: زیرنام برنامه
-  setting_welcome_text: نوشتار خوش‌آمد گویی
+  setting_welcome_text: متن خوش‌آمد گویی
   setting_default_language: زبان پیش‌گزیده
   setting_login_required: الزامی بودن ورود
   setting_self_registration: خود نام نویسی
@@ -323,23 +322,23 @@ fa:
   setting_text_formatting: قالب بندی نوشته
   setting_wiki_compression: فشرده‌سازی پیشینه ویکی
   setting_feeds_limit: کرانه محتوای خوراک
-  setting_default_projects_public: حالت پیش‌گزیده پروژه‌های تازه، همگانی است
+  setting_default_projects_public: حالت پیش‌گزیده پروژه‌های جدید، همگانی است
   setting_autofetch_changesets: دریافت خودکار تغییرات
-  setting_sys_api_enabled: فعال سازی وب سرویس برای سرپرستی انباره
+  setting_sys_api_enabled: فعال سازی وب سرویس برای مدیریت بایگانی
   setting_commit_ref_keywords: کلیدواژه‌های نشانه
   setting_commit_fix_keywords: کلیدواژه‌های انجام
   setting_autologin: ورود خودکار
   setting_date_format: قالب تاریخ
   setting_time_format: قالب زمان
-  setting_cross_project_issue_relations: توانایی وابستگی میان پروژه‌ای پیامدها
-  setting_issue_list_default_columns: ستون‌های پیش‌گزیده نمایش داده شده در فهرست پیامدها
+  setting_cross_project_issue_relations: توانایی وابستگی میان پروژه‌ای موردها
+  setting_issue_list_default_columns: ستون‌های پیش‌گزیده نمایش داده شده در فهرست موردها
   setting_emails_header: سرنویس ایمیل‌ها
   setting_emails_footer: پانویس ایمیل‌ها
   setting_protocol: پیوندنامه
   setting_per_page_options: گزینه‌های اندازه داده‌های هر برگ
   setting_user_format: قالب نمایشی کاربران
   setting_activity_days_default: روزهای نمایش داده شده در گزارش پروژه
-  setting_display_subprojects_issues: پیش‌گزیده نمایش پیامدهای زیرپروژه در پروژه پدر
+  setting_display_subprojects_issues: پیش‌گزیده نمایش موردهای زیرپروژه در پروژه پدر
   setting_enabled_scm: فعالسازی SCM
   setting_mail_handler_body_delimiters: "بریدن ایمیل‌ها پس از یکی از این ردیف‌ها"
   setting_mail_handler_api_enabled: فعالسازی وب سرویس برای ایمیل‌های آمده
@@ -352,162 +351,162 @@ fa:
   setting_repository_log_display_limit: بیشترین شمار نگارش‌های نمایش داده شده در گزارش پرونده
   setting_openid: پذیرش ورود و نام نویسی با OpenID
   setting_password_min_length: کمترین اندازه گذرواژه
-  setting_new_project_user_role_id: نقش داده شده به کاربری که سرپرست نیست و پروژه می‌سازد
-  setting_default_projects_modules: پیمانه‌های پیش‌گزیده فعال برای پروژه‌های تازه
-  setting_issue_done_ratio: برآورد اندازه انجام شده پیامد با
-  setting_issue_done_ratio_issue_field: کاربرد فیلد پیامد
-  setting_issue_done_ratio_issue_status: کاربرد وضعیت پیامد
-  setting_start_of_week: آغاز گاهشمار از
+  setting_new_project_user_role_id: نقش داده شده به کاربری که مدیر سایت نیست و پروژه می‌سازد
+  setting_default_projects_modules: پودمان های پیش‌گزیده فعال برای پروژه‌های جدید
+  setting_issue_done_ratio: برآورد اندازه انجام شده مورد با
+  setting_issue_done_ratio_issue_field: کاربرد فیلد مورد
+  setting_issue_done_ratio_issue_status: کاربرد وضعیت مورد
+  setting_start_of_week: آغاز تقویم از
   setting_rest_api_enabled: فعالسازی وب سرویس‌های REST
   setting_cache_formatted_text: نهان سازی نوشته‌های قالب بندی شده
   setting_default_notification_option: آگاه سازی پیش‌گزیده
-  setting_commit_logtime_enabled: فعالسازی زمان گذاشته شده
-  setting_commit_logtime_activity_id: کار زمان گذاشته شده
+  setting_commit_logtime_enabled: فعالسازی زمان صرف شده
+  setting_commit_logtime_activity_id: کد فعالیت زمان صرف شده
   setting_gantt_items_limit: بیشترین شمار بخش‌های نمایش داده شده در نمودار گانت
 
   permission_add_project: ساخت پروژه
   permission_add_subprojects: ساخت زیرپروژه
   permission_edit_project: ویرایش پروژه
-  permission_select_project_modules: گزینش پیمانه‌های پروژه
-  permission_manage_members: سرپرستی اعضا
-  permission_manage_project_activities: سرپرستی کارهای پروژه
-  permission_manage_versions: سرپرستی نگارش‌ها
-  permission_manage_categories: سرپرستی دسته‌های پیامد
-  permission_view_issues: دیدن پیامدها
-  permission_add_issues: افزودن پیامدها
-  permission_edit_issues: ویرایش پیامدها
-  permission_manage_issue_relations: سرپرستی وابستگی پیامدها
+  permission_select_project_modules: گزینش پودمان های پروژه
+  permission_manage_members: مدیریت همکاران پروژه
+  permission_manage_project_activities: مدیریت کارهای پروژه
+  permission_manage_versions: مدیریت نگارش‌ها
+  permission_manage_categories: مدیریت دسته بندی موارد
+  permission_view_issues: دیدن موردها
+  permission_add_issues: افزودن موردها
+  permission_edit_issues: ویرایش موردها
+  permission_manage_issue_relations: مدیریت وابستگی موردها
   permission_add_issue_notes: افزودن یادداشت
   permission_edit_issue_notes: ویرایش یادداشت
   permission_edit_own_issue_notes: ویرایش یادداشت خود
-  permission_move_issues: جابجایی پیامدها
-  permission_delete_issues: پاک کردن پیامدها
-  permission_manage_public_queries: سرپرستی پرس‌وجوهای همگانی
+  permission_move_issues: جابجایی موردها
+  permission_delete_issues: پاک کردن موردها
+  permission_manage_public_queries: مدیریت پرس‌وجوهای همگانی
   permission_save_queries: ذخیره سازی پرس‌وجوها
   permission_view_gantt: دیدن نمودار گانت
-  permission_view_calendar: دیدن گاهشمار
+  permission_view_calendar: دیدن تقویم
   permission_view_issue_watchers: دیدن فهرست دیده‌بان‌ها
   permission_add_issue_watchers: افزودن دیده‌بان‌ها
   permission_delete_issue_watchers: پاک کردن دیده‌بان‌ها
-  permission_log_time: نوشتن زمان گذاشته شده
-  permission_view_time_entries: دیدن زمان گذاشته شده
-  permission_edit_time_entries: ویرایش زمان گذاشته شده
-  permission_edit_own_time_entries: ویرایش زمان گذاشته شده خود
-  permission_manage_news: سرپرستی رویدادها
-  permission_comment_news: گذاشتن دیدگاه روی رویدادها
-  permission_view_documents: دیدن نوشتارها
-  permission_manage_files: سرپرستی پرونده‌ها
+  permission_log_time: نوشتن زمان صرف شده
+  permission_view_time_entries: دیدن زمان صرف شده
+  permission_edit_time_entries: ویرایش زمان صرف شده
+  permission_edit_own_time_entries: ویرایش زمان صرف شده خود
+  permission_manage_news: مدیریت اخبار
+  permission_comment_news: افزودن نظر شخصی به مجموعه اخبار
+  permission_view_documents: دیدن مستندات
+  permission_manage_files: مدیریت پرونده‌ها
   permission_view_files: دیدن پرونده‌ها
-  permission_manage_wiki: سرپرستی ویکی
-  permission_rename_wiki_pages: نامگذاری برگه ویکی
-  permission_delete_wiki_pages: پاک کردن برگه ویکی
+  permission_manage_wiki: مدیریت ویکی
+  permission_rename_wiki_pages: نامگذاری صفحه ویکی
+  permission_delete_wiki_pages: پاک کردن صفحه ویکی
   permission_view_wiki_pages: دیدن ویکی
   permission_view_wiki_edits: دیدن پیشینه ویکی
-  permission_edit_wiki_pages: ویرایش برگه‌های ویکی
-  permission_delete_wiki_pages_attachments: پاک کردن پیوست‌های برگه ویکی
-  permission_protect_wiki_pages: نگه‌داری برگه‌های ویکی
-  permission_manage_repository: سرپرستی انباره
-  permission_browse_repository: چریدن در انباره
+  permission_edit_wiki_pages: ویرایش صفحه‌های ویکی
+  permission_delete_wiki_pages_attachments: پاک کردن پیوست‌های صفحه ویکی
+  permission_protect_wiki_pages: نگه‌داری صفحه‌های ویکی
+  permission_manage_repository: مدیریت بایگانی
+  permission_browse_repository: مرور و بررسی در بایگانی
   permission_view_changesets: دیدن تغییرات
-  permission_commit_access: دسترسی تغییر انباره
-  permission_manage_boards: سرپرستی انجمن‌ها
+  permission_commit_access: دسترسی تغییر بایگانی
+  permission_manage_boards: مدیریت انجمن‌ها
   permission_view_messages: دیدن پیام‌ها
   permission_add_messages: فرستادن پیام‌ها
   permission_edit_messages: ویرایش پیام‌ها
   permission_edit_own_messages: ویرایش پیام خود
   permission_delete_messages: پاک کردن پیام‌ها
   permission_delete_own_messages: پاک کردن پیام خود
-  permission_export_wiki_pages: صدور برگه‌های ویکی
-  permission_manage_subtasks: سرپرستی زیرکارها
+  permission_export_wiki_pages: صدور صفحه‌های ویکی
+  permission_manage_subtasks: مدیریت زیرکارها
 
-  project_module_issue_tracking: پیگیری پیامدها
+  project_module_issue_tracking: پیگیری موردها
   project_module_time_tracking: پیگیری زمان
-  project_module_news: رویدادها
-  project_module_documents: نوشتارها
+  project_module_news: اخبار
+  project_module_documents: مستندات
   project_module_files: پرونده‌ها
   project_module_wiki: ویکی
-  project_module_repository: انباره
+  project_module_repository: بایگانی
   project_module_boards: انجمن‌ها
-  project_module_calendar: گاهشمار
+  project_module_calendar: تقویم
   project_module_gantt: گانت
 
   label_user: کاربر
   label_user_plural: کاربر
-  label_user_new: کاربر تازه
+  label_user_new: کاربر جدید
   label_user_anonymous: ناشناس
   label_project: پروژه
-  label_project_new: پروژه تازه
-  label_project_plural: پروژه
+  label_project_new: پروژه جدید
+  label_project_plural: پروژه ها
   label_x_projects:
     zero:  بدون پروژه
     one:   "1 پروژه"
     other: "%{count} پروژه"
   label_project_all: همه پروژه‌ها
   label_project_latest: آخرین پروژه‌ها
-  label_issue: پیامد
-  label_issue_new: پیامد تازه
-  label_issue_plural: پیامد
-  label_issue_view_all: دیدن همه پیامدها
-  label_issues_by: "دسته‌بندی پیامدها با %{value}"
-  label_issue_added: پیامد افزوده شد
-  label_issue_updated: پیامد بروز شد
-  label_document: نوشتار
-  label_document_new: نوشتار تازه
-  label_document_plural: نوشتار
-  label_document_added: نوشتار افزوده شد
+  label_issue: مورد
+  label_issue_new: مورد جدید
+  label_issue_plural: موردها
+  label_issue_view_all: دیدن همه موردها
+  label_issues_by: "دسته‌بندی موردها با %{value}"
+  label_issue_added: مورد افزوده شد
+  label_issue_updated: مورد بروز شد
+  label_document: مستند
+  label_document_new: مستند جدید
+  label_document_plural: مستندات
+  label_document_added: مستند افزوده شد
   label_role: نقش
-  label_role_plural: نقش
-  label_role_new: نقش تازه
-  label_role_and_permissions: نقش‌ها و پروانه‌ها
-  label_member: عضو
-  label_member_new: عضو تازه
-  label_member_plural: عضو
-  label_tracker: پیگرد
-  label_tracker_plural: پیگرد
-  label_tracker_new: پیگرد تازه
+  label_role_plural: نقش ها
+  label_role_new: نقش جدید
+  label_role_and_permissions: نقش‌ها و مجوز‌ها
+  label_member: همکار
+  label_member_new: همکار جدید
+  label_member_plural: همکاران
+  label_tracker: ردیاب
+  label_tracker_plural: ردیاب ها
+  label_tracker_new: ردیاب جدید
   label_workflow: گردش کار
-  label_issue_status: وضعیت پیامد
-  label_issue_status_plural: وضعیت پیامد
-  label_issue_status_new: وضعیت تازه
-  label_issue_category: دسته پیامد
-  label_issue_category_plural: دسته پیامد
-  label_issue_category_new: دسته تازه
+  label_issue_status: وضعیت مورد
+  label_issue_status_plural: وضعیت موارد
+  label_issue_status_new: وضعیت جدید
+  label_issue_category: دسته بندی مورد
+  label_issue_category_plural: دسته بندی موارد
+  label_issue_category_new: دسته بندی جدید
   label_custom_field: فیلد سفارشی
-  label_custom_field_plural: فیلد سفارشی
-  label_custom_field_new: فیلد سفارشی تازه
+  label_custom_field_plural: فیلدهای سفارشی
+  label_custom_field_new: فیلد سفارشی جدید
   label_enumerations: برشمردنی‌ها
-  label_enumeration_new: مقدار تازه
+  label_enumeration_new: مقدار جدید
   label_information: داده
-  label_information_plural: داده
+  label_information_plural: داده ها
   label_please_login: وارد شوید
   label_register: نام نویسی کنید
   label_login_with_open_id_option: یا با OpenID وارد شوید
   label_password_lost: بازیافت گذرواژه
-  label_home: سرآغاز
-  label_my_page: برگه من
-  label_my_account: حساب من
-  label_my_projects: پروژه‌های من
-  label_my_page_block: بخش برگه من
-  label_administration: سرپرستی
-  label_login: ورود
+  label_home: پیش خوان
+  label_my_page: صفحه خودم
+  label_my_account: تنظیمات خودم
+  label_my_projects: پروژه‌های خودم
+  label_my_page_block: بخش صفحه خودم
+  label_administration: مدیریت
+  label_login: نام کاربری
   label_logout: خروج
   label_help: راهنما
-  label_reported_issues: پیامدهای گزارش شده
-  label_assigned_to_me_issues: پیامدهای واگذار شده به من
+  label_reported_issues: موردهای گزارش شده
+  label_assigned_to_me_issues: موردهای واگذار شده به من
   label_last_login: آخرین ورود
   label_registered_on: نام نویسی شده در
-  label_activity: گزارش
-  label_overall_activity: گزارش روی هم رفته
-  label_user_activity: "گزارش %{value}"
-  label_new: تازه
+  label_activity: گزارش فعالیت ها
+  label_overall_activity: کل فعالیت ها روی هم رفته
+  label_user_activity: "درصد فعالیت %{value}"
+  label_new: جدید
   label_logged_as: "نام کاربری:"
   label_environment: محیط
   label_authentication: شناسایی
   label_auth_source: روش شناسایی
-  label_auth_source_new: روش شناسایی تازه
-  label_auth_source_plural: روش شناسایی
-  label_subproject_plural: زیرپروژه
-  label_subproject_new: زیرپروژه تازه
+  label_auth_source_new: روش شناسایی جدید
+  label_auth_source_plural: روش های شناسایی
+  label_subproject_plural: زیرپروژه ها
+  label_subproject_new: زیرپروژه جدید
   label_and_its_subprojects: "%{value} و زیرپروژه‌هایش"
   label_min_max_length: کمترین و بیشترین اندازه
   label_list: فهرست
@@ -518,28 +517,28 @@ fa:
   label_string: نوشته
   label_text: نوشته بلند
   label_attribute: نشانه
-  label_attribute_plural: نشانه
+  label_attribute_plural: نشانه ها
   label_no_data: هیچ داده‌ای برای نمایش نیست
   label_change_status: جایگزینی وضعیت
   label_history: پیشینه
   label_attachment: پرونده
-  label_attachment_new: پرونده تازه
+  label_attachment_new: پرونده جدید
   label_attachment_delete: پاک کردن پرونده
   label_attachment_plural: پرونده
   label_file_added: پرونده افزوده شد
   label_report: گزارش
-  label_report_plural: گزارش
-  label_news: رویداد
-  label_news_new: افزودن رویداد
-  label_news_plural: رویداد
-  label_news_latest: آخرین رویدادها
-  label_news_view_all: دیدن همه رویدادها
-  label_news_added: رویداد افزوده شد
+  label_report_plural: گزارشات
+  label_news: اخبار
+  label_news_new: افزودن خبر
+  label_news_plural: اخبار
+  label_news_latest: آخرین اخبار
+  label_news_view_all: دیدن همه اخبار
+  label_news_added: خبر افزوده شد
   label_settings: پیکربندی
   label_overview: در یک نگاه
   label_version: نگارش
-  label_version_new: نگارش تازه
-  label_version_plural: نگارش
+  label_version_new: نگارش جدید
+  label_version_plural: نگارش ها
   label_close_versions: بستن نگارش‌های انجام شده
   label_confirmation: بررسی
   label_export_to: 'قالب‌های دیگر:'
@@ -561,40 +560,40 @@ fa:
     zero:  0 بسته
     one:   1 بسته
     other: "%{count} بسته"
-  label_total: جمله
-  label_permissions: پروانه‌ها
+  label_total: مجموعا
+  label_permissions: مجوز‌ها
   label_current_status: وضعیت کنونی
-  label_new_statuses_allowed: وضعیت‌های پذیرفتنی تازه
+  label_new_statuses_allowed: وضعیت‌های پذیرفتنی جدید
   label_all: همه
   label_none: هیچ
   label_nobody: هیچکس
   label_next: پسین
   label_previous: پیشین
   label_used_by: به کار رفته در
-  label_details: ریزه‌کاری
+  label_details: جزئیات
   label_add_note: افزودن یادداشت
-  label_per_page: ردیف‌ها در هر برگه
-  label_calendar: گاهشمار
+  label_per_page: ردیف‌ها در هر صفحه
+  label_calendar: تقویم
   label_months_from: از ماه
   label_gantt: گانت
   label_internal: درونی
   label_last_changes: "%{count} تغییر آخر"
   label_change_view_all: دیدن همه تغییرات
-  label_personalize_page: سفارشی نمودن این برگه
-  label_comment: دیدگاه
-  label_comment_plural: دیدگاه
+  label_personalize_page: سفارشی نمودن این صفحه
+  label_comment: نظر
+  label_comment_plural: نظر ها
   label_x_comments:
-    zero: بدون دیدگاه
-    one: 1 دیدگاه
-    other: "%{count} دیدگاه"
-  label_comment_add: افزودن دیدگاه
-  label_comment_added: دیدگاه افزوده شد
-  label_comment_delete: پاک کردن دیدگاه‌ها
+    zero: بدون نظر
+    one: 1 نظر
+    other: "%{count} نظر"
+  label_comment_add: افزودن نظر
+  label_comment_added: نظر افزوده شد
+  label_comment_delete: پاک کردن نظر‌ها
   label_query: پرس‌وجوی سفارشی
-  label_query_plural: پرس‌وجوی سفارشی
-  label_query_new: پرس‌وجوی تازه
+  label_query_plural: پرس‌وجوی های سفارشی
+  label_query_new: پرس‌وجوی جدید
   label_filter_add: افزودن پالایه
-  label_filter_plural: پالایه
+  label_filter_plural: پالایه ها
   label_equals: برابر است با
   label_not_equals: برابر نیست با
   label_in_less_than: کمتر است از
@@ -618,50 +617,50 @@ fa:
   label_contains: دارد
   label_not_contains: ندارد
   label_day_plural: روز
-  label_repository: انباره
-  label_repository_plural: انباره
-  label_browse: چریدن
+  label_repository: بایگانی
+  label_repository_plural: بایگانی ها
+  label_browse: مرور و بررسی
   label_branch: شاخه
   label_tag: برچسب
-  label_revision: بازبینی
-  label_revision_plural: بازبینی
-  label_revision_id: "بازبینی %{value}"
-  label_associated_revisions: بازبینی‌های وابسته
+  label_revision: شماره بازنگری
+  label_revision_plural: شماره بازنگری‌ها
+  label_revision_id: "بازنگری %{value}"
+  label_associated_revisions: بازنگری‌های وابسته
   label_added: افزوده شده
   label_modified: پیراسته شده
   label_copied: رونویسی شده
   label_renamed: نامگذاری شده
   label_deleted: پاکسازی شده
-  label_latest_revision: آخرین بازبینی
-  label_latest_revision_plural: آخرین بازبینی
-  label_view_revisions: دیدن بازبینی‌ها
-  label_view_all_revisions: دیدن همه بازبینی‌ها
+  label_latest_revision: آخرین بازنگری‌
+  label_latest_revision_plural: آخرین بازنگری‌ها
+  label_view_revisions: دیدن بازنگری‌ها
+  label_view_all_revisions: دیدن همه بازنگری‌ها
   label_max_size: بیشترین اندازه
   label_sort_highest: بردن به آغاز
   label_sort_higher: بردن به بالا
   label_sort_lower: بردن به پایین
   label_sort_lowest: بردن به پایان
-  label_roadmap: چشم‌انداز
+  label_roadmap: نقشه راه
   label_roadmap_due_in: "سررسید در %{value}"
   label_roadmap_overdue: "%{value} دیرکرد"
-  label_roadmap_no_issues: هیچ پیامدی برای این نگارش نیست
+  label_roadmap_no_issues: هیچ موردی برای این نگارش نیست
   label_search: جستجو
   label_result_plural: دست‌آورد
   label_all_words: همه واژه‌ها
   label_wiki: ویکی
   label_wiki_edit: ویرایش ویکی
   label_wiki_edit_plural: ویرایش ویکی
-  label_wiki_page: برگه ویکی
-  label_wiki_page_plural: برگه ویکی
+  label_wiki_page: صفحه ویکی
+  label_wiki_page_plural: صفحه ویکی
   label_index_by_title: شاخص بر اساس نام
   label_index_by_date: شاخص بر اساس تاریخ
   label_current_version: نگارش کنونی
   label_preview: پیش‌نمایش
   label_feed_plural: خوراک
   label_changes_details: ریز همه جایگذاری‌ها
-  label_issue_tracking: پیگیری پیامد
-  label_spent_time: زمان گذاشته شده
-  label_overall_spent_time: زمان گذاشته شده روی هم
+  label_issue_tracking: پیگیری موارد
+  label_spent_time: زمان صرف شده
+  label_overall_spent_time: زمان صرف شده روی هم
   label_f_hour: "%{value} ساعت"
   label_f_hour_plural: "%{value} ساعت"
   label_time_tracking: پیگیری زمان
@@ -674,12 +673,12 @@ fa:
   label_diff_side_by_side: کنار به کنار
   label_options: گزینه‌ها
   label_copy_workflow_from: رونویسی گردش کار از روی
-  label_permissions_report: گزارش پروانه‌ها
-  label_watched_issues: پیامدهای دیده‌بانی شده
-  label_related_issues: پیامدهای وابسته
+  label_permissions_report: گزارش مجوز‌ها
+  label_watched_issues: موردهای دیده‌بانی شده
+  label_related_issues: موردهای وابسته
   label_applied_status: وضعیت به کار رفته
   label_loading: بار گذاری...
-  label_relation_new: وابستگی تازه
+  label_relation_new: وابستگی جدید
   label_relation_delete: پاک کردن وابستگی
   label_relates_to: وابسته به
   label_duplicates: نگارش دیگری از
@@ -697,14 +696,14 @@ fa:
   label_show_completed_versions: نمایش نگارش‌های انجام شده
   label_me: من
   label_board: انجمن
-  label_board_new: انجمن تازه
+  label_board_new: انجمن جدید
   label_board_plural: انجمن
   label_board_locked: قفل شده
   label_board_sticky: چسبناک
   label_topic_plural: سرفصل
   label_message_plural: پیام
   label_message_last: آخرین پیام
-  label_message_new: پیام تازه
+  label_message_new: پیام جدید
   label_message_posted: پیام افزوده شد
   label_reply_plural: پاسخ
   label_send_information: فرستادن داده‌های حساب به کاربر
@@ -719,7 +718,7 @@ fa:
   label_feeds_access_key: کلید دسترسی Atom
   label_missing_feeds_access_key: کلید دسترسی Atom در دسترس نیست
   label_feeds_access_key_created_on: "کلید دسترسی Atom %{value} پیش ساخته شده است"
-  label_module_plural: پیمانه
+  label_module_plural: پودمان ها
   label_added_time_by: "افزوده شده به دست %{author} در %{age} پیش"
   label_updated_time_by: "بروز شده به دست %{author} در %{age} پیش"
   label_updated_time: "بروز شده در %{value} پیش"
@@ -728,13 +727,13 @@ fa:
   label_changeset_plural: تغییر
   label_default_columns: ستون‌های پیش‌گزیده
   label_no_change_option: (بدون تغییر)
-  label_bulk_edit_selected_issues: ویرایش دسته‌ای پیامدهای گزینش شده
+  label_bulk_edit_selected_issues: ویرایش گروهی‌ موردهای گزینش شده
   label_theme: پوسته
   label_default: پیش‌گزیده
   label_search_titles_only: تنها نام‌ها جستجو شود
-  label_user_mail_option_all: "برای هر رویداد در همه پروژه‌ها"
-  label_user_mail_option_selected: "برای هر رویداد تنها در پروژه‌های گزینش شده..."
-  label_user_mail_option_none: "هیچ رویدادی"
+  label_user_mail_option_all: "برای هر خبر در همه پروژه‌ها"
+  label_user_mail_option_selected: "برای هر خبر تنها در پروژه‌های گزینش شده..."
+  label_user_mail_option_none: "هیچ خبری"
   label_user_mail_option_only_my_events: "تنها برای چیزهایی که دیده‌بان هستم یا در آن‌ها درگیر هستم"
   label_user_mail_option_only_assigned: "تنها برای چیزهایی که به من واگذار شده"
   label_user_mail_option_only_owner: "تنها برای چیزهایی که من دارنده آن‌ها هستم"
@@ -742,7 +741,7 @@ fa:
   label_registration_activation_by_email: فعالسازی حساب با ایمیل
   label_registration_manual_activation: فعالسازی حساب دستی
   label_registration_automatic_activation: فعالسازی حساب خودکار
-  label_display_per_page: "ردیف‌ها در هر برگه: %{value}"
+  label_display_per_page: "ردیف‌ها در هر صفحه: %{value}"
   label_age: سن
   label_change_properties: ویرایش ویژگی‌ها
   label_general: همگانی
@@ -751,7 +750,7 @@ fa:
   label_plugins: افزونه‌ها
   label_ldap_authentication: شناساییLDAP
   label_downloads_abbr: دریافت
-  label_optional_description: یادداشت دلخواه
+  label_optional_description: توضیحات دلخواه
   label_add_another_file: افزودن پرونده دیگر
   label_preferences: پسندها
   label_chronological_order: به ترتیب تاریخ
@@ -766,34 +765,34 @@ fa:
   label_ascending: افزایشی
   label_descending: کاهشی
   label_date_from_to: از %{start} تا %{end}
-  label_wiki_content_added: برگه ویکی افزوده شد
-  label_wiki_content_updated: برگه ویکی بروز شد
-  label_group: دسته
-  label_group_plural: دسته
-  label_group_new: دسته تازه
-  label_time_entry_plural: زمان گذاشته شده
+  label_wiki_content_added: صفحه ویکی افزوده شد
+  label_wiki_content_updated: صفحه ویکی بروز شد
+  label_group: گروه
+  label_group_plural: گروهها
+  label_group_new: گروه جدید
+  label_time_entry_plural: زمان های صرف شده
   label_version_sharing_none: بدون اشتراک
   label_version_sharing_descendants: با زیر پروژه‌ها
   label_version_sharing_hierarchy: با رشته پروژه‌ها
   label_version_sharing_tree: با درخت پروژه
   label_version_sharing_system: با همه پروژه‌ها
-  label_update_issue_done_ratios: بروز رسانی اندازه انجام شده پیامد
+  label_update_issue_done_ratios: بروز رسانی اندازه انجام شده مورد
   label_copy_source: منبع
   label_copy_target: مقصد
   label_copy_same_as_target: مانند مقصد
-  label_display_used_statuses_only: تنها وضعیت‌هایی نشان داده شوند که در این پیگرد به کار رفته‌اند
+  label_display_used_statuses_only: تنها وضعیت‌هایی نشان داده شوند که در این ردیاب به کار رفته‌اند
   label_api_access_key: کلید دسترسی API
   label_missing_api_access_key: کلید دسترسی API در دسترس نیست
   label_api_access_key_created_on: "کلید دسترسی API %{value} پیش ساخته شده است"
   label_profile: نمایه
   label_subtask_plural: زیرکار
   label_project_copy_notifications: در هنگام رونویسی پروژه ایمیل‌های آگاه‌سازی را بفرست
-  label_principal_search: "جستجو برای کاربر یا دسته:"
+  label_principal_search: "جستجو برای کاربر یا گروه:"
   label_user_search: "جستجو برای کاربر:"
 
   button_login: ورود
-  button_submit: واگذاری
-  button_save: نگهداری
+  button_submit: ارسال
+  button_save: ذخیره
   button_check_all: گزینش همه
   button_uncheck_all: گزینش هیچ
   button_delete: پاک
@@ -801,7 +800,7 @@ fa:
   button_create_and_continue: ساخت و ادامه
   button_test: آزمایش
   button_edit: ویرایش
-  button_edit_associated_wikipage: "ویرایش برگه ویکی وابسته: %{page_title}"
+  button_edit_associated_wikipage: "ویرایش صفحه ویکی وابسته: %{page_title}"
   button_add: افزودن
   button_change: ویرایش
   button_apply: انجام
@@ -826,7 +825,7 @@ fa:
   button_unarchive: برگشت از بایگانی
   button_reset: بازنشانی
   button_rename: نامگذاری
-  button_change_password: جایگزینی گذرواژه
+  button_change_password: تغییر گذرواژه
   button_copy: رونوشت
   button_copy_and_follow: رونوشت و ادامه
   button_annotate: یادداشت
@@ -851,73 +850,73 @@ fa:
   text_min_max_length_info: 0 یعنی بدون کران
   text_project_destroy_confirmation: آیا براستی می‌خواهید این پروژه و همه داده‌های آن را پاک کنید؟
   text_subprojects_destroy_warning: "زیرپروژه‌های آن: %{value} هم پاک خواهند شد."
-  text_workflow_edit: یک نقش و یک پیگرد را برای ویرایش گردش کار برگزینید
+  text_workflow_edit: یک نقش و یک ردیاب را برای ویرایش گردش کار برگزینید
   text_are_you_sure: آیا این کار انجام شود؟
   text_journal_changed: "«%{label}» از «%{old}» به «%{new}» جایگزین شد"
-  text_journal_set_to: "«%{label}» به «%{value}» نشانده شد"
+  text_journal_set_to: "«%{label}» به «%{value}» تغییر یافت"
   text_journal_deleted: "«%{label}» پاک شد (%{old})"
   text_journal_added: "«%{label}»، «%{value}» را افزود"
-  text_tip_task_begin_day: روز آغاز پیامد
-  text_tip_task_end_day: روز پایان پیامد
-  text_tip_task_begin_end_day: روز آغاز و پایان پیامد
+  text_tip_task_begin_day: روز آغاز مورد
+  text_tip_task_end_day: روز پایان مورد
+  text_tip_task_begin_end_day: روز آغاز و پایان مورد
   text_caracters_maximum: "بیشترین اندازه %{count} است."
   text_caracters_minimum: "کمترین اندازه %{count} است."
   text_length_between: "باید میان %{min} و %{max} نویسه باشد."
-  text_tracker_no_workflow: هیچ گردش کاری برای این پیگرد مشخص نشده است
+  text_tracker_no_workflow: هیچ گردش کاری برای این ردیاب مشخص نشده است
   text_unallowed_characters: نویسه‌های ناپسند
   text_comma_separated: چند مقدار پذیرفتنی است (با «,» از هم جدا شوند).
   text_line_separated: چند مقدار پذیرفتنی است (هر مقدار در یک خط).
-  text_issues_ref_in_commit_messages: نشانه روی و بستن پیامدها در پیام‌های انباره
-  text_issue_added: "پیامد %{id} به دست %{author} گزارش شد."
-  text_issue_updated: "پیامد %{id} به دست %{author} بروز شد."
+  text_issues_ref_in_commit_messages: نشانه روی و بستن موردها در پیام‌های بایگانی
+  text_issue_added: "مورد %{id} به دست %{author} گزارش شد."
+  text_issue_updated: "مورد %{id} به دست %{author} بروز شد."
   text_wiki_destroy_confirmation: آیا براستی می‌خواهید این ویکی و همه محتوای آن را پاک کنید؟
-  text_issue_category_destroy_question: "برخی پیامدها (%{count}) به این دسته واگذار شده‌اند. می‌خواهید چه کنید؟"
-  text_issue_category_destroy_assignments: پاک کردن واگذاری به دسته
-  text_issue_category_reassign_to: واگذاری دوباره پیامدها به این دسته
-  text_user_mail_option: "برای پروژه‌های گزینش نشده، تنها ایمیل‌هایی درباره چیزهایی که دیده‌بان یا درگیر آن‌ها هستید دریافت خواهید کرد (مانند پیامدهایی که نویسنده آن‌ها هستید یا به شما واگذار شده‌اند)."
-  text_no_configuration_data: "نقش‌ها، پیگردها، وضعیت‌های پیامد و گردش کار هنوز پیکربندی نشده‌اند. \nبه سختی پیشنهاد می‌شود که پیکربندی پیش‌گزیده را بار کنید. سپس می‌توانید آن را ویرایش کنید."
+  text_issue_category_destroy_question: "برخی موردها (%{count}) به این دسته بندی واگذار شده‌اند. می‌خواهید چه کنید؟"
+  text_issue_category_destroy_assignments: پاک کردن واگذاریها به دسته بندی موارد
+  text_issue_category_reassign_to: واگذاری دوباره موردها به این دسته بندی
+  text_user_mail_option: "برای پروژه‌های گزینش نشده، تنها ایمیل‌هایی درباره چیزهایی که دیده‌بان یا درگیر آن‌ها هستید دریافت خواهید کرد (مانند موردهایی که نویسنده آن‌ها هستید یا به شما واگذار شده‌اند)."
+  text_no_configuration_data: "نقش‌ها، ردیابها، وضعیت‌های مورد و گردش کار هنوز پیکربندی نشده‌اند. \nبه سختی پیشنهاد می‌شود که پیکربندی پیش‌گزیده را بار کنید. سپس می‌توانید آن را ویرایش کنید."
   text_load_default_configuration: بارگذاری پیکربندی پیش‌گزیده
   text_status_changed_by_changeset: "در تغییر %{value} بروز شده است."
   text_time_logged_by_changeset: "در تغییر %{value} نوشته شده است."
-  text_issues_destroy_confirmation: 'آیا براستی می‌خواهید پیامدهای گزینش شده را پاک کنید؟'
-  text_select_project_modules: 'پیمانه‌هایی که باید برای این پروژه فعال شوند را برگزینید:'
-  text_default_administrator_account_changed: حساب سرپرستی پیش‌گزیده جایگزین شد
+  text_issues_destroy_confirmation: 'آیا براستی می‌خواهید موردهای گزینش شده را پاک کنید؟'
+  text_select_project_modules: 'پودمان هایی که باید برای این پروژه فعال شوند را برگزینید:'
+  text_default_administrator_account_changed: حساب مدیریت پیش‌گزیده جایگزین شد
   text_file_repository_writable: پوشه پیوست‌ها نوشتنی است
   text_plugin_assets_writable: پوشه دارایی‌های افزونه‌ها نوشتنی است
   text_rmagick_available: RMagick در دسترس است (اختیاری)
-  text_destroy_time_entries_question: "%{hours} ساعت روی پیامدهایی که می‌خواهید پاک کنید کار گزارش شده است. می‌خواهید چه کنید؟"
+  text_destroy_time_entries_question: "%{hours} ساعت روی موردهایی که می‌خواهید پاک کنید کار گزارش شده است. می‌خواهید چه کنید؟"
   text_destroy_time_entries: ساعت‌های گزارش شده پاک شوند
   text_assign_time_entries_to_project: ساعت‌های گزارش شده به پروژه واگذار شوند
-  text_reassign_time_entries: 'ساعت‌های گزارش شده به این پیامد واگذار شوند:'
+  text_reassign_time_entries: 'ساعت‌های گزارش شده به این مورد واگذار شوند:'
   text_user_wrote: "%{value} نوشت:"
   text_enumeration_destroy_question: "%{count} داده به این برشمردنی وابسته شده‌اند."
   text_enumeration_category_reassign_to: 'به این برشمردنی وابسته شوند:'
   text_email_delivery_not_configured: "دریافت ایمیل پیکربندی نشده است و آگاه‌سازی‌ها غیر فعال هستند.\nکارگزار SMTP خود را در config/configuration.yml پیکربندی کنید و برنامه را بازنشانی کنید تا فعال شوند."
-  text_repository_usernames_mapping: "کاربر Redmine که به هر نام کاربری پیام‌های انباره نگاشت می‌شود را برگزینید.\nکاربرانی که نام کاربری یا ایمیل همسان دارند، خود به خود نگاشت می‌شوند."
+  text_repository_usernames_mapping: "کاربر Redmine که به هر نام کاربری پیام‌های بایگانی نگاشت می‌شود را برگزینید.\nکاربرانی که نام کاربری یا ایمیل همسان دارند، خود به خود نگاشت می‌شوند."
   text_diff_truncated: '... این تفاوت بریده شده چون بیشتر از بیشترین اندازه نمایش دادنی است.'
   text_custom_field_possible_values_info: 'یک خط برای هر مقدار'
-  text_wiki_page_destroy_question: "این برگه %{descendants} زیربرگه دارد.می‌خواهید چه کنید؟"
-  text_wiki_page_nullify_children: "زیربرگه‌ها برگه ریشه شوند"
-  text_wiki_page_destroy_children: "زیربرگه‌ها و زیربرگه‌های آن‌ها پاک شوند"
-  text_wiki_page_reassign_children: "زیربرگه‌ها به زیر این برگه پدر بروند"
-  text_own_membership_delete_confirmation: "شما دارید برخی یا همه پروانه‌های خود را برمی‌دارید و شاید پس از این دیگر نتوانید این پروژه را ویرایش کنید.\nآیا می‌خواهید این کار را بکنید؟"
+  text_wiki_page_destroy_question: "این صفحه %{descendants} زیرصفحه دارد.می‌خواهید چه کنید؟"
+  text_wiki_page_nullify_children: "زیرصفحه‌ها صفحه ریشه شوند"
+  text_wiki_page_destroy_children: "زیرصفحه‌ها و زیرصفحه‌های آن‌ها پاک شوند"
+  text_wiki_page_reassign_children: "زیرصفحه‌ها به زیر این صفحه پدر بروند"
+  text_own_membership_delete_confirmation: "شما دارید برخی یا همه مجوز‌های خود را برمی‌دارید و شاید پس از این دیگر نتوانید این پروژه را ویرایش کنید.\nآیا می‌خواهید این کار را بکنید؟"
   text_zoom_in: درشتنمایی
   text_zoom_out: ریزنمایی
 
-  default_role_manager: سرپرست
+  default_role_manager: مدیر سایت
   default_role_developer: برنامه‌نویس
   default_role_reporter: گزارش‌دهنده
   default_tracker_bug: ایراد
   default_tracker_feature: ویژگی
   default_tracker_support: پشتیبانی
-  default_issue_status_new: تازه
+  default_issue_status_new: جدید
   default_issue_status_in_progress: در گردش
   default_issue_status_resolved: درست شده
   default_issue_status_feedback: بازخورد
   default_issue_status_closed: بسته
   default_issue_status_rejected: برگشت خورده
-  default_doc_category_user: نوشتار کاربر
-  default_doc_category_tech: نوشتار فنی
+  default_doc_category_user: مستندات کاربر
+  default_doc_category_tech: مستندات فنی
   default_priority_low: پایین
   default_priority_normal: میانه
   default_priority_high: بالا
@@ -926,42 +925,42 @@ fa:
   default_activity_design: طراحی
   default_activity_development: ساخت
 
-  enumeration_issue_priorities: برتری‌های پیامد
-  enumeration_doc_categories: دسته‌های نوشتار
-  enumeration_activities: کارها (پیگیری زمان)
-  enumeration_system_activity: کار سامانه
+  enumeration_issue_priorities: اولویت‌های مورد
+  enumeration_doc_categories: دسته بندی‌های مستندات
+  enumeration_activities: فعالیت ها (پیگیری زمان)
+  enumeration_system_activity: فعالیت سیستمی
 
-  text_tip_issue_begin_day: پیامد در این روز آغاز می‌شود
-  field_warn_on_leaving_unsaved: هنگام ترک برگه‌ای که نوشته‌های آن نگهداری نشده، به من هشدار بده
-  text_tip_issue_begin_end_day: پیامد در این روز آغاز می‌شود و پایان می‌پذیرد
-  text_tip_issue_end_day: پیامد در این روز پایان می‌پذیرد
-  text_warn_on_leaving_unsaved: این برگه دارای نوشته‌های نگهداری نشده است که اگر آن را ترک کنید، از میان می‌روند.
-  label_my_queries: جستارهای سفارشی من
+  text_tip_issue_begin_day: مورد در این روز آغاز می‌شود
+  field_warn_on_leaving_unsaved: هنگام ترک صفحه‌ای که نوشته‌های آن ذخیره نشده، به من هشدار بده
+  text_tip_issue_begin_end_day: مورد در این روز آغاز می‌شود و پایان می‌پذیرد
+  text_tip_issue_end_day: مورد در این روز پایان می‌پذیرد
+  text_warn_on_leaving_unsaved: این صفحه دارای نوشته‌های ذخیره نشده است که اگر آن را ترک کنید، از میان می‌روند.
+  label_my_queries: جستارهای سفارشی خودم
   text_journal_changed_no_detail: "%{label} بروز شد"
-  label_news_comment_added: دیدگاه به یک رویداد افزوده شد
+  label_news_comment_added: نظر شخصی به مجموعه اخبار افزوده شد
   button_expand_all: باز کردن همه
   button_collapse_all: بستن همه
-  label_additional_workflow_transitions_for_assignee: زمانی که به کاربر واگذار شده، گذارهای بیشتر پذیرفته می‌شود
+  label_additional_workflow_transitions_for_assignee: زمانی که به فرد مسئول، گذارهای بیشتر پذیرفته می‌شود
   label_additional_workflow_transitions_for_author: زمانی که کاربر نویسنده است، گذارهای بیشتر پذیرفته می‌شود
-  label_bulk_edit_selected_time_entries: ویرایش دسته‌ای زمان‌های گزارش شده گزینش شده
+  label_bulk_edit_selected_time_entries: ویرایش گروهی زمان‌های گزارش شده گزینش شده
   text_time_entries_destroy_confirmation: آیا می‌خواهید زمان‌های گزارش شده گزینش شده پاک شوند؟
   label_role_anonymous: ناشناس
-  label_role_non_member: غیر عضو
+  label_role_non_member: غیر همکار
   label_issue_note_added: یادداشت افزوده شد
   label_issue_status_updated: وضعیت بروز شد
-  label_issue_priority_updated: برتری بروز شد
-  label_issues_visibility_own: Issues created by or assigned to the user
-  field_issues_visibility: Issues visibility
-  label_issues_visibility_all: All issues
-  permission_set_own_issues_private: Set own issues public or private
-  field_is_private: Private
-  permission_set_issues_private: Set issues public or private
-  label_issues_visibility_public: All non private issues
+  label_issue_priority_updated: اولویت بروز شد
+  label_issues_visibility_own: موردهای ایجاد شده تو سط خود کاربر و یا محول شده به وی
+  field_issues_visibility: امکان مشاهده موارد
+  label_issues_visibility_all: همه موارد
+  permission_set_own_issues_private: اجازه دارد موردهای خود را خصوصی یا عمومی نماید
+  field_is_private: خصوصی
+  permission_set_issues_private: اجازه دارد موردها را خصوصی یا عمومی نماید
+  label_issues_visibility_public: همه موردهای غیر خصوصی
   text_issues_destroy_descendants_confirmation: This will also delete %{count} subtask(s).
-  field_commit_logs_encoding: کدگذاری پیام‌های انباره
-  field_scm_path_encoding: Path encoding
+  field_commit_logs_encoding: کدگذاری پیام‌های بایگانی
+  field_scm_path_encoding: Path encoding نحوه کدگذاری مسیر یا
   text_scm_path_encoding_note: "Default: UTF-8"
-  field_path_to_repository: Path to repository
+  field_path_to_repository: مسیر بایگانی
   field_root_directory: Root directory
   field_cvs_module: Module
   field_cvsroot: CVSROOT
@@ -1003,11 +1002,11 @@ fa:
   error_attachment_too_big: This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})
   notice_failed_to_save_time_entries: "Failed to save %{count} time entrie(s) on %{total} selected: %{ids}."
   label_x_issues:
-    zero:  0 پیامد
-    one:   1 پیامد
-    other: "%{count} پیامد"
-  label_repository_new: New repository
-  field_repository_is_default: Main repository
+    zero:  0 مورد
+    one:   1 مورد
+    other: "%{count} مورد"
+  label_repository_new: بایگانی جدید
+  field_repository_is_default: بایگانی پیش گزیده
   label_copy_attachments: Copy attachments
   label_item_position: "%{position}/%{count}"
   label_completed_versions: Completed versions
@@ -1027,13 +1026,13 @@ fa:
   text_account_destroy_confirmation: |-
     Are you sure you want to proceed?
     Your account will be permanently deleted, with no way to reactivate it.
-  error_session_expired: Your session has expired. Please login again.
-  text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
-  setting_session_lifetime: Session maximum lifetime
-  setting_session_timeout: Session inactivity timeout
-  label_session_expiration: Session expiration
-  permission_close_project: Close / reopen the project
-  label_show_closed_projects: View closed projects
+  error_session_expired: .مهلت اعتبار ارتباط شما با سایت پایان یافته، لطفا دوباره وارد شوید
+  text_session_expiration_settings: "اخطار: تغییر در این تنظیمات ممکن است منجر به انقضای اعتبار جلسات افراد از جمله خود شما شود"
+  setting_session_lifetime: حداکثر زمان حفظ برقراری ارتباط با سایت
+  setting_session_timeout: مدت زمان ارتباط بدون فعالیت
+  label_session_expiration: انقضای ارتباط با سایت
+  permission_close_project: باز یا بستن پروژه
+  label_show_closed_projects: نمایش پروژه های بسته شده
   button_close: Close
   button_reopen: Reopen
   project_status_active: active
@@ -1045,36 +1044,36 @@ fa:
   field_timeout: Timeout (in seconds)
   setting_thumbnails_enabled: Display attachment thumbnails
   setting_thumbnails_size: Thumbnails size (in pixels)
-  label_status_transitions: Status transitions
-  label_fields_permissions: Fields permissions
-  label_readonly: Read-only
-  label_required: Required
+  label_status_transitions: نحوه تغییر وضعیت مورد
+  label_fields_permissions: مجوز فیلدها
+  label_readonly: فقط خواندنی
+  label_required: الزامی
   text_repository_identifier_info: Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.
   field_board_parent: Parent forum
-  label_attribute_of_project: Project's %{name}
-  label_attribute_of_author: Author's %{name}
-  label_attribute_of_assigned_to: Assignee's %{name}
-  label_attribute_of_fixed_version: Target version's %{name}
+  label_attribute_of_project: از فرم پروژه -- %{name}
+  label_attribute_of_author: از فرم نویسنده -- %{name}
+  label_attribute_of_assigned_to: از فرم فرد مسئول -- %{name}
+  label_attribute_of_fixed_version: از فرم نگارش -- %{name}
   label_copy_subtasks: Copy subtasks
-  label_copied_to: copied to
-  label_copied_from: copied from
-  label_any_issues_in_project: any issues in project
-  label_any_issues_not_in_project: any issues not in project
-  field_private_notes: Private notes
-  permission_view_private_notes: View private notes
-  permission_set_notes_private: Set notes as private
-  label_no_issues_in_project: no issues in project
+  label_copied_to: مواردی که کپی شده اند به
+  label_copied_from: مواردی که کپی شده اند از
+  label_any_issues_in_project: کلیه مواردی که در این پروژه باشند
+  label_any_issues_not_in_project: کلیه مواردی که در این پروژه نباشند
+  field_private_notes: یادداشت های خصوصی
+  permission_view_private_notes: مشاهده یادداشت های خصوصی
+  permission_set_notes_private: می تواند یادداشت ها را خصوصی کند
+  label_no_issues_in_project: هیچ موردی در این پروژه وجود نداشته باشد
   label_any: همه
-  label_last_n_weeks: last %{count} weeks
-  setting_cross_project_subtasks: Allow cross-project subtasks
+  label_last_n_weeks: هفته اخیر %{count}
+  setting_cross_project_subtasks: مجوز تعریف فعالیت های بین پروژه ای
   label_cross_project_descendants: با زیر پروژه‌ها
   label_cross_project_tree: با درخت پروژه
   label_cross_project_hierarchy: با رشته پروژه‌ها
   label_cross_project_system: با همه پروژه‌ها
   button_hide: Hide
-  setting_non_working_week_days: Non-working days
-  label_in_the_next_days: in the next
-  label_in_the_past_days: in the past
+  setting_non_working_week_days: روزهای غیرکاری
+  label_in_the_next_days: در روزهای بعد
+  label_in_the_past_days: در روزهای گذشته
   label_attribute_of_user: User's %{name}
   text_turning_multiple_off: If you disable multiple values, multiple values will be
     removed in order to preserve only one value per item.
@@ -1084,11 +1083,11 @@ fa:
   permission_delete_documents: Delete documents
   label_gantt_progress_line: Progress line
   setting_jsonp_enabled: Enable JSONP support
-  field_inherit_members: Inherit members
+  field_inherit_members: همکاران هم بصورت موروثی منتقل شوند
   field_closed_on: Closed
   field_generate_password: Generate password
   setting_default_projects_tracker_ids: Default trackers for new projects
-  label_total_time: جمله
+  label_total_time: کل زمان
   text_scm_config: You can configure your SCM commands in config/configuration.yml. Please restart the application after editing it.
   text_scm_command_not_available: SCM command is not available. Please check settings on the administration panel.
   notice_account_not_activated_yet: You haven't activated your account yet. If you want
@@ -1114,6 +1113,7 @@ fa:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index b31ae68..51e076e 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -1133,6 +1133,7 @@ fi:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index c9213ad..7fa72ff 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -15,8 +15,11 @@ fr:
 
     day_names: [dimanche, lundi, mardi, mercredi, jeudi, vendredi, samedi]
     abbr_day_names: [dim, lun, mar, mer, jeu, ven, sam]
+
+    # Don't forget the nil at the beginning; there's no such thing as a 0th month
     month_names: [~, janvier, février, mars, avril, mai, juin, juillet, août, septembre, octobre, novembre, décembre]
     abbr_month_names: [~, jan., fév., mar., avr., mai, juin, juil., août, sept., oct., nov., déc.]
+    # Used in date_select and datime_select.
     order:
       - :day
       - :month
@@ -183,14 +186,16 @@ fr:
   notice_email_sent: "Un email a été envoyé à %{value}"
   notice_email_error: "Erreur lors de l'envoi de l'email (%{value})"
   notice_feeds_access_key_reseted: "Votre clé d'accès aux flux Atom a été réinitialisée."
+  notice_api_access_key_reseted: Votre clé d'accès API a été réinitialisée.
   notice_failed_to_save_issues: "%{count} demande(s) sur les %{total} sélectionnées n'ont pas pu être mise(s) à jour : %{ids}."
   notice_failed_to_save_time_entries: "%{count} temps passé(s) sur les %{total} sélectionnés n'ont pas pu être mis à jour: %{ids}."
+  notice_failed_to_save_members: "Erreur lors de la sauvegarde des membres: %{errors}."
   notice_no_issue_selected: "Aucune demande sélectionnée ! Cochez les demandes que vous voulez mettre à jour."
   notice_account_pending: "Votre compte a été créé et attend l'approbation de l'administrateur."
   notice_default_data_loaded: Paramétrage par défaut chargé avec succès.
   notice_unable_delete_version: Impossible de supprimer cette version.
+  notice_unable_delete_time_entry: Impossible de supprimer le temps passé.
   notice_issue_done_ratios_updated: L'avancement des demandes a été mis à jour.
-  notice_api_access_key_reseted: Votre clé d'accès API a été réinitialisée.
   notice_gantt_chart_truncated: "Le diagramme a été tronqué car il excède le nombre maximal d'éléments pouvant être affichés (%{max})"
   notice_issue_successful_create: "Demande %{id} créée."
   notice_issue_update_conflict: "La demande a été mise à jour par un autre utilisateur pendant que vous la modifiez."
@@ -202,15 +207,22 @@ fr:
   error_scm_not_found: "L'entrée et/ou la révision demandée n'existe pas dans le dépôt."
   error_scm_command_failed: "Une erreur s'est produite lors de l'accès au dépôt : %{value}"
   error_scm_annotate: "L'entrée n'existe pas ou ne peut pas être annotée."
+  error_scm_annotate_big_text_file: Cette entrée ne peut pas être annotée car elle excède la taille maximale.
   error_issue_not_found_in_project: "La demande n'existe pas ou n'appartient pas à ce projet"
+  error_no_tracker_in_project: "Aucun tracker n'est associé à ce projet. Vérifier la configuration du projet."
+  error_no_default_issue_status: "Aucun statut de demande n'est défini par défaut. Vérifier votre configuration (Administration -> Statuts de demandes)."
+  error_can_not_delete_custom_field: Impossible de supprimer le champ personnalisé
+  error_can_not_delete_tracker: Ce tracker contient des demandes et ne peut pas être supprimé.
+  error_can_not_remove_role: Ce rôle est utilisé et ne peut pas être supprimé.
   error_can_not_reopen_issue_on_closed_version: 'Une demande assignée à une version fermée ne peut pas être réouverte'
   error_can_not_archive_project: "Ce projet ne peut pas être archivé"
+  error_issue_done_ratios_not_updated: L'avancement des demandes n'a pas pu être mis à jour.
   error_workflow_copy_source: 'Veuillez sélectionner un tracker et/ou un rôle source'
   error_workflow_copy_target: 'Veuillez sélectionner les trackers et rôles cibles'
-  error_issue_done_ratios_not_updated: L'avancement des demandes n'a pas pu être mis à jour.
+  error_unable_delete_issue_status: Impossible de supprimer le statut de demande
+  error_unable_to_connect: Connexion impossible (%{value})
   error_attachment_too_big: Ce fichier ne peut pas être attaché car il excède la taille maximale autorisée (%{max_size})
   error_session_expired: "Votre session a expiré. Veuillez vous reconnecter."
-
   warning_attachments_not_saved: "%{count} fichier(s) n'ont pas pu être sauvegardés."
 
   mail_subject_lost_password: "Votre mot de passe %{value}"
@@ -228,7 +240,6 @@ fr:
   mail_subject_wiki_content_updated: "Page wiki '%{id}' mise à jour"
   mail_body_wiki_content_updated: "La page wiki '%{id}' a été mise à jour par %{author}."
 
-
   field_name: Nom
   field_description: Description
   field_summary: Résumé
@@ -265,6 +276,7 @@ fr:
   field_priority: Priorité
   field_fixed_version: Version cible
   field_user: Utilisateur
+  field_principal: Principal
   field_role: Rôle
   field_homepage: Site web
   field_is_public: Public
@@ -309,6 +321,7 @@ fr:
   field_redirect_existing_links: Rediriger les liens existants
   field_estimated_hours: Temps estimé
   field_column_names: Colonnes
+  field_time_entries: Temps passé
   field_time_zone: Fuseau horaire
   field_searchable: Utilisé pour les recherches
   field_default_value: Valeur par défaut
@@ -320,13 +333,20 @@ fr:
   field_content: Contenu
   field_group_by: Grouper par
   field_sharing: Partage
-  field_active: Actif
   field_parent_issue: Tâche parente
+  field_member_of_group: Groupe de l'assigné
+  field_assigned_to_role: Rôle de l'assigné
+  field_text: Champ texte
   field_visible: Visible
   field_warn_on_leaving_unsaved: "M'avertir lorsque je quitte une page contenant du texte non sauvegardé"
   field_issues_visibility: Visibilité des demandes
   field_is_private: Privée
   field_commit_logs_encoding: Encodage des messages de commit
+  field_scm_path_encoding: Encodage des chemins
+  field_path_to_repository: Chemin du dépôt
+  field_root_directory: Répertoire racine
+  field_cvsroot: CVSROOT
+  field_cvs_module: Module
   field_repository_is_default: Dépôt principal
   field_multiple: Valeurs multiples
   field_auth_source_ldap_filter: Filtre LDAP
@@ -364,6 +384,8 @@ fr:
   setting_cross_project_issue_relations: Autoriser les relations entre demandes de différents projets
   setting_cross_project_subtasks: Autoriser les sous-tâches dans des projets différents
   setting_issue_list_default_columns: Colonnes affichées par défaut sur la liste des demandes
+  setting_repositories_encodings: Encodages des fichiers et des dépôts
+  setting_emails_header: En-tête des emails
   setting_emails_footer: Pied-de-page des emails
   setting_protocol: Protocole
   setting_per_page_options: Options d'objets affichés par page
@@ -376,6 +398,7 @@ fr:
   setting_mail_handler_api_key: Clé de protection de l'API
   setting_sequential_project_identifiers: Générer des identifiants de projet séquentiels
   setting_gravatar_enabled: Afficher les Gravatar des utilisateurs
+  setting_gravatar_default: Image Gravatar par défaut
   setting_diff_max_lines_displayed: Nombre maximum de lignes de diff affichées
   setting_file_max_size_displayed: Taille maximum des fichiers texte affichés en ligne
   setting_repository_log_display_limit: "Nombre maximum de révisions affichées sur l'historique d'un fichier"
@@ -384,12 +407,12 @@ fr:
   setting_new_project_user_role_id: Rôle donné à un utilisateur non-administrateur qui crée un projet
   setting_default_projects_modules: Modules activés par défaut pour les nouveaux projets
   setting_issue_done_ratio: Calcul de l'avancement des demandes
-  setting_issue_done_ratio_issue_status: Utiliser le statut
   setting_issue_done_ratio_issue_field: 'Utiliser le champ % effectué'
-  setting_rest_api_enabled: Activer l'API REST
-  setting_gravatar_default: Image Gravatar par défaut
+  setting_issue_done_ratio_issue_status: Utiliser le statut
   setting_start_of_week: Jour de début des calendriers
+  setting_rest_api_enabled: Activer l'API REST
   setting_cache_formatted_text: Mettre en cache le texte formaté
+  setting_default_notification_option: Option de notification par défaut
   setting_commit_logtime_enabled: Permettre la saisie de temps
   setting_commit_logtime_activity_id: Activité pour le temps saisi
   setting_gantt_items_limit: Nombre maximum d'éléments affichés sur le gantt
@@ -414,6 +437,7 @@ fr:
   permission_close_project: Fermer / réouvrir le projet
   permission_select_project_modules: Choisir les modules
   permission_manage_members: Gérer les membres
+  permission_manage_project_activities: Gérer les activités
   permission_manage_versions: Gérer les versions
   permission_manage_categories: Gérer les catégories de demandes
   permission_view_issues: Voir les demandes
@@ -468,7 +492,6 @@ fr:
   permission_delete_messages: Supprimer les messages
   permission_delete_own_messages: Supprimer ses propres messages
   permission_export_wiki_pages: Exporter les pages
-  permission_manage_project_activities: Gérer les activités
   permission_manage_subtasks: Gérer les sous-tâches
   permission_manage_related_issues: Gérer les demandes associées
 
@@ -480,6 +503,8 @@ fr:
   project_module_wiki: Wiki
   project_module_repository: Dépôt de sources
   project_module_boards: Forums de discussion
+  project_module_calendar: Calendrier
+  project_module_gantt: Gantt
 
   label_user: Utilisateur
   label_user_plural: Utilisateurs
@@ -498,12 +523,13 @@ fr:
   label_issue_new: Nouvelle demande
   label_issue_plural: Demandes
   label_issue_view_all: Voir toutes les demandes
+  label_issues_by: "Demandes par %{value}"
   label_issue_added: Demande ajoutée
   label_issue_updated: Demande mise à jour
   label_issue_note_added: Note ajoutée
   label_issue_status_updated: Statut changé
+  label_issue_assigned_to_updated: Assigné changé
   label_issue_priority_updated: Priorité changée
-  label_issues_by: "Demandes par %{value}"
   label_document: Document
   label_document_new: Nouveau document
   label_document_plural: Documents
@@ -596,6 +622,7 @@ fr:
   label_version: Version
   label_version_new: Nouvelle version
   label_version_plural: Versions
+  label_close_versions: Fermer les versions terminées
   label_confirmation: Confirmation
   label_export_to: 'Formats disponibles :'
   label_read: Lire...
@@ -663,6 +690,9 @@ fr:
   label_in_more_than: dans plus de
   label_in_the_next_days: dans les prochains jours
   label_in_the_past_days: dans les derniers jours
+  label_greater_or_equal: '>='
+  label_less_or_equal: '<='
+  label_between: entre
   label_in: dans
   label_today: aujourd'hui
   label_all_time: toute la période
@@ -688,8 +718,11 @@ fr:
   label_repository_new: Nouveau dépôt
   label_repository_plural: Dépôts
   label_browse: Parcourir
+  label_branch: Branche
+  label_tag: Tag
   label_revision: Révision
   label_revision_plural: Révisions
+  label_revision_id: "Révision %{value}"
   label_associated_revisions: Révisions associées
   label_added: ajouté
   label_modified: modifié
@@ -699,6 +732,7 @@ fr:
   label_latest_revision: Dernière révision
   label_latest_revision_plural: Dernières révisions
   label_view_revisions: Voir les révisions
+  label_view_all_revisions: Voir toutes les révisions
   label_max_size: Taille maximale
   label_sort_highest: Remonter en premier
   label_sort_higher: Remonter
@@ -724,6 +758,7 @@ fr:
   label_changes_details: Détails de tous les changements
   label_issue_tracking: Suivi des demandes
   label_spent_time: Temps passé
+  label_overall_spent_time: Temps passé global
   label_f_hour: "%{value} heure"
   label_f_hour_plural: "%{value} heures"
   label_time_tracking: Suivi du temps
@@ -731,6 +766,7 @@ fr:
   label_statistics: Statistiques
   label_commits_per_month: Commits par mois
   label_commits_per_author: Commits par auteur
+  label_diff: diff
   label_view_diff: Voir les différences
   label_diff_inline: en ligne
   label_diff_side_by_side: côte à côte
@@ -763,6 +799,8 @@ fr:
   label_board: Forum
   label_board_new: Nouveau forum
   label_board_plural: Forums
+  label_board_locked: Verrouillé
+  label_board_sticky: Sticky
   label_topic_plural: Discussions
   label_message_plural: Messages
   label_message_last: Dernier message
@@ -778,6 +816,8 @@ fr:
   label_language_based: Basé sur la langue de l'utilisateur
   label_sort_by: "Trier par %{value}"
   label_send_test_email: Envoyer un email de test
+  label_feeds_access_key: Clé d'accès Atom
+  label_missing_feeds_access_key: Clé d'accès Atom manquante
   label_feeds_access_key_created_on: "Clé d'accès Atom créée il y a %{value}"
   label_module_plural: Modules
   label_added_time_by: "Ajouté par %{author} il y a %{age}"
@@ -789,11 +829,16 @@ fr:
   label_default_columns: Colonnes par défaut
   label_no_change_option: (Pas de changement)
   label_bulk_edit_selected_issues: Modifier les demandes sélectionnées
+  label_bulk_edit_selected_time_entries: Modifier les temps passés sélectionnés
   label_theme: Thème
   label_default: Défaut
   label_search_titles_only: Uniquement dans les titres
   label_user_mail_option_all: "Pour tous les événements de tous mes projets"
   label_user_mail_option_selected: "Pour tous les événements des projets sélectionnés..."
+  label_user_mail_option_none: Aucune notification
+  label_user_mail_option_only_my_events: Seulement pour ce que je surveille
+  label_user_mail_option_only_assigned: Seulement pour ce qui m'est assigné
+  label_user_mail_option_only_owner: Seulement pour ce que j'ai créé
   label_user_mail_no_self_notified: "Je ne veux pas être notifié des changements que j'effectue"
   label_registration_activation_by_email: activation du compte par email
   label_registration_manual_activation: activation manuelle du compte
@@ -824,8 +869,8 @@ fr:
   label_date_from_to: Du %{start} au %{end}
   label_wiki_content_added: Page wiki ajoutée
   label_wiki_content_updated: Page wiki mise à jour
-  label_group_plural: Groupes
   label_group: Groupe
+  label_group_plural: Groupes
   label_group_new: Nouveau groupe
   label_time_entry_plural: Temps passé
   label_version_sharing_none: Non partagé
@@ -833,18 +878,14 @@ fr:
   label_version_sharing_hierarchy: Avec toute la hiérarchie
   label_version_sharing_tree: Avec tout l'arbre
   label_version_sharing_system: Avec tous les projets
+  label_update_issue_done_ratios: Mettre à jour l'avancement des demandes
   label_copy_source: Source
   label_copy_target: Cible
   label_copy_same_as_target: Comme la cible
-  label_update_issue_done_ratios: Mettre à jour l'avancement des demandes
   label_display_used_statuses_only: N'afficher que les statuts utilisés dans ce tracker
   label_api_access_key: Clé d'accès API
-  label_api_access_key_created_on: Clé d'accès API créée il y a %{value}
-  label_feeds_access_key: Clé d'accès Atom
   label_missing_api_access_key: Clé d'accès API manquante
-  label_missing_feeds_access_key: Clé d'accès Atom manquante
-  label_close_versions: Fermer les versions terminées
-  label_revision_id: Révision %{value}
+  label_api_access_key_created_on: Clé d'accès API créée il y a %{value}
   label_profile: Profil
   label_subtask_plural: Sous-tâches
   label_project_copy_notifications: Envoyer les notifications durant la copie du projet
@@ -855,11 +896,15 @@ fr:
   label_issues_visibility_all: Toutes les demandes
   label_issues_visibility_public: Toutes les demandes non privées
   label_issues_visibility_own: Demandes créées par ou assignées à l'utilisateur
+  label_git_report_last_commit: Afficher le dernier commit des fichiers et répertoires
+  label_parent_revision: Parent
+  label_child_revision: Enfant
   label_export_options: Options d'exportation %{export_format}
   label_copy_attachments: Copier les fichiers
   label_copy_subtasks: Copier les sous-tâches
   label_item_position: "%{position} sur %{count}"
   label_completed_versions: Versions passées
+  label_search_for_watchers: Rechercher des observateurs
   label_session_expiration: Expiration des sessions
   label_show_closed_projects: Voir les projets fermés
   label_status_transitions: Changements de statut
@@ -904,6 +949,7 @@ fr:
   button_create_and_continue: Créer et continuer
   button_test: Tester
   button_edit: Modifier
+  button_edit_associated_wikipage: "Modifier la page wiki associée: %{page_title}"
   button_add: Ajouter
   button_change: Changer
   button_apply: Appliquer
@@ -956,6 +1002,8 @@ fr:
   version_status_locked: verrouillé
   version_status_closed: fermé
 
+  field_active: Actif
+
   text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
   text_regexp_info: ex. ^[A-Z0-9]+$
   text_min_max_length_info: 0 pour aucune restriction
@@ -963,6 +1011,11 @@ fr:
   text_subprojects_destroy_warning: "Ses sous-projets : %{value} seront également supprimés."
   text_workflow_edit: Sélectionner un tracker et un rôle pour éditer le workflow
   text_are_you_sure: Êtes-vous sûr ?
+  text_journal_changed: "%{label} changé de %{old} à %{new}"
+  text_journal_changed_no_detail: "%{label} mis à jour"
+  text_journal_set_to: "%{label} mis à %{value}"
+  text_journal_deleted: "%{label} %{old} supprimé"
+  text_journal_added: "%{label} %{value} ajouté"
   text_tip_issue_begin_day: tâche commençant ce jour
   text_tip_issue_end_day: tâche finissant ce jour
   text_tip_issue_begin_end_day: tâche commençant et finissant ce jour
@@ -988,11 +1041,13 @@ fr:
   text_time_logged_by_changeset: "Appliqué par commit %{value}"
   text_issues_destroy_confirmation: 'Êtes-vous sûr de vouloir supprimer la ou les demandes(s) selectionnée(s) ?'
   text_issues_destroy_descendants_confirmation: "Cela entrainera également la suppression de %{count} sous-tâche(s)."
+  text_time_entries_destroy_confirmation: "Etes-vous sûr de vouloir supprimer les temps passés sélectionnés ?"
   text_select_project_modules: 'Sélectionner les modules à activer pour ce projet :'
   text_default_administrator_account_changed: Compte administrateur par défaut changé
   text_file_repository_writable: Répertoire de stockage des fichiers accessible en écriture
   text_plugin_assets_writable: Répertoire public des plugins accessible en écriture
   text_rmagick_available: Bibliothèque RMagick présente (optionnelle)
+  text_convert_available: Binaire convert de ImageMagick présent (optionel)
   text_destroy_time_entries_question: "%{hours} heures ont été enregistrées sur les demandes à supprimer. Que voulez-vous faire ?"
   text_destroy_time_entries: Supprimer les heures
   text_assign_time_entries_to_project: Reporter les heures sur le projet
@@ -1009,7 +1064,16 @@ fr:
   text_wiki_page_destroy_children: "Supprimer les sous-pages et toutes leurs descedantes"
   text_wiki_page_reassign_children: "Réaffecter les sous-pages à cette page"
   text_own_membership_delete_confirmation: "Vous allez supprimer tout ou partie de vos permissions sur ce projet et ne serez peut-être plus autorisé à modifier ce projet.\nEtes-vous sûr de vouloir continuer ?"
+  text_zoom_in: Zoom avant
+  text_zoom_out: Zoom arrière
   text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardé qui sera perdu si vous quittez la page."
+  text_scm_path_encoding_note: "Défaut : UTF-8"
+  text_git_repository_note: "Le dépôt est vide et local (exemples : /gitrepo, c:\\gitrepo)"
+  text_mercurial_repository_note: "Dépôt local (exemples : /hgrepo, c:\\hgrepo)"
+  text_scm_command: Commande
+  text_scm_command_version: Version
+  text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification.
+  text_scm_command_not_available: Ce SCM n'est pas disponible. Vérifier les paramètres dans la section administration.
   text_issue_conflict_resolution_overwrite: "Appliquer quand même ma mise à jour (les notes précédentes seront conservées mais des changements pourront être écrasés)"
   text_issue_conflict_resolution_add_notes: "Ajouter mes notes et ignorer mes autres changements"
   text_issue_conflict_resolution_cancel: "Annuler ma mise à jour et réafficher %{link}"
@@ -1043,84 +1107,23 @@ fr:
   enumeration_issue_priorities: Priorités des demandes
   enumeration_doc_categories: Catégories des documents
   enumeration_activities: Activités (suivi du temps)
-  label_greater_or_equal: ">="
-  label_less_or_equal: "<="
-  label_between: entre
-  label_view_all_revisions: Voir toutes les révisions
-  label_tag: Tag
-  label_branch: Branche
-  error_no_tracker_in_project: "Aucun tracker n'est associé à ce projet. Vérifier la configuration du projet."
-  error_no_default_issue_status: "Aucun statut de demande n'est défini par défaut. Vérifier votre configuration (Administration -> Statuts de demandes)."
-  text_journal_changed: "%{label} changé de %{old} à %{new}"
-  text_journal_changed_no_detail: "%{label} mis à jour"
-  text_journal_set_to: "%{label} mis à %{value}"
-  text_journal_deleted: "%{label} %{old} supprimé"
-  text_journal_added: "%{label} %{value} ajouté"
   enumeration_system_activity: Activité système
-  label_board_sticky: Sticky
-  label_board_locked: Verrouillé
-  error_unable_delete_issue_status: Impossible de supprimer le statut de demande
-  error_can_not_delete_custom_field: Impossible de supprimer le champ personnalisé
-  error_unable_to_connect: Connexion impossible (%{value})
-  error_can_not_remove_role: Ce rôle est utilisé et ne peut pas être supprimé.
-  error_can_not_delete_tracker: Ce tracker contient des demandes et ne peut pas être supprimé.
-  field_principal: Principal
-  notice_failed_to_save_members: "Erreur lors de la sauvegarde des membres: %{errors}."
-  text_zoom_out: Zoom arrière
-  text_zoom_in: Zoom avant
-  notice_unable_delete_time_entry: Impossible de supprimer le temps passé.
-  label_overall_spent_time: Temps passé global
-  field_time_entries: Temps passé
-  project_module_gantt: Gantt
-  project_module_calendar: Calendrier
-  button_edit_associated_wikipage: "Modifier la page wiki associée: %{page_title}"
-  field_text: Champ texte
-  label_user_mail_option_only_owner: Seulement pour ce que j'ai créé
-  setting_default_notification_option: Option de notification par défaut
-  label_user_mail_option_only_my_events: Seulement pour ce que je surveille
-  label_user_mail_option_only_assigned: Seulement pour ce qui m'est assigné
-  label_user_mail_option_none: Aucune notification
-  field_member_of_group: Groupe de l'assigné
-  field_assigned_to_role: Rôle de l'assigné
-  setting_emails_header: En-tête des emails
-  label_bulk_edit_selected_time_entries: Modifier les temps passés sélectionnés
-  text_time_entries_destroy_confirmation: "Etes-vous sûr de vouloir supprimer les temps passés sélectionnés ?"
-  field_scm_path_encoding: Encodage des chemins
-  text_scm_path_encoding_note: "Défaut : UTF-8"
-  field_path_to_repository: Chemin du dépôt
-  field_root_directory: Répertoire racine
-  field_cvs_module: Module
-  field_cvsroot: CVSROOT
-  text_mercurial_repository_note: "Dépôt local (exemples : /hgrepo, c:\\hgrepo)"
-  text_scm_command: Commande
-  text_scm_command_version: Version
-  label_git_report_last_commit: Afficher le dernier commit des fichiers et répertoires
-  text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification.
-  text_scm_command_not_available: Ce SCM n'est pas disponible. Vérifier les paramètres dans la section administration.
-  label_diff: diff
-  text_git_repository_note: "Le dépôt est vide et local (exemples : /gitrepo, c:\\gitrepo)"
-  description_query_sort_criteria_direction: Ordre de tri
-  description_project_scope: Périmètre de recherche
   description_filter: Filtre
-  description_user_mail_notification: Option de notification
-  description_date_from: Date de début
+  description_search: Champ de recherche
+  description_choose_project: Projets
+  description_project_scope: Périmètre de recherche
+  description_notes: Notes
   description_message_content: Contenu du message
+  description_query_sort_criteria_attribute: Critère de tri
+  description_query_sort_criteria_direction: Ordre de tri
+  description_user_mail_notification: Option de notification
   description_available_columns: Colonnes disponibles
+  description_selected_columns: Colonnes sélectionnées
   description_all_columns: Toutes les colonnes
-  description_date_range_interval: Choisir une période
   description_issue_category_reassign: Choisir une catégorie
-  description_search: Champ de recherche
-  description_notes: Notes
+  description_wiki_subpages_reassign: Choisir une nouvelle page parent
   description_date_range_list: Choisir une période prédéfinie
-  description_choose_project: Projets
+  description_date_range_interval: Choisir une période
+  description_date_from: Date de début
   description_date_to: Date de fin
-  description_query_sort_criteria_attribute: Critère de tri
-  description_wiki_subpages_reassign: Choisir une nouvelle page parent
-  description_selected_columns: Colonnes sélectionnées
-  label_parent_revision: Parent
-  label_child_revision: Enfant
-  error_scm_annotate_big_text_file: Cette entrée ne peut pas être annotée car elle excède la taille maximale.
-  setting_repositories_encodings: Encodages des fichiers et des dépôts
-  label_search_for_watchers: Rechercher des observateurs
   text_repository_identifier_info: 'Seuls les lettres minuscules (a-z), chiffres, tirets et tirets bas sont autorisés.<br />Un fois sauvegardé, l''identifiant ne pourra plus être modifié.'
-  text_convert_available: Binaire convert de ImageMagick présent (optionel)
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index e3859df..e6e9fe8 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -1123,6 +1123,7 @@ gl:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/he.yml b/config/locales/he.yml
index 843354d..03c5f9d 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -1117,6 +1117,7 @@ he:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/hr.yml b/config/locales/hr.yml
index a21fe8c..3915dbe 100644
--- a/config/locales/hr.yml
+++ b/config/locales/hr.yml
@@ -1113,6 +1113,7 @@ hr:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index 4768c79..53900a3 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -1131,6 +1131,7 @@
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/id.yml b/config/locales/id.yml
index eee676d..9075bd4 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -1116,6 +1116,7 @@ id:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/it.yml b/config/locales/it.yml
index 92efb5c..1bc2340 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -1111,6 +1111,7 @@ it:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 3296e41..c80e2ae 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -162,14 +162,6 @@ ja:
   general_csv_separator: ','
   general_csv_decimal_separator: '.'
   general_csv_encoding: CP932
-  ## Redmine 1.2.0 現在、この値によって、pdfの出力のフォントを切り替えています。
-  ## CRuby では CP932 にしてください。
-  ## JRuby 1.6.2 (ruby-1.8.7-p330) では、CP932 ですと
-  ## Iconv::InvalidEncoding例外が発生します。
-  ## JRuby では、SJIS か Shift_JIS にしてください。
-  ## ご存知の通り、CP932 と SJIS は別物ですが、
-  ## そこまでの検証はしていません。
-  # general_pdf_encoding: SJIS
   general_pdf_encoding: CP932
   general_first_day_of_week: '7'
 
@@ -354,13 +346,13 @@ ja:
   setting_attachment_max_size: 添付ファイルサイズの上限
   setting_issues_export_limit: エクスポートするチケット数の上限
   setting_mail_from: 送信元メールアドレス
-  setting_bcc_recipients: ブラインドカーボンコピーで受信(bcc)
-  setting_plain_text_mail: プレインテキストのみ(HTMLなし)
-  setting_host_name: ホスト名
+  setting_bcc_recipients: 宛先を非表示(bcc)
+  setting_plain_text_mail: プレインテキスト形式(HTMLなし)
+  setting_host_name: ホスト名とパス
   setting_text_formatting: テキストの書式
   setting_cache_formatted_text: 書式化されたテキストをキャッシュする
   setting_wiki_compression: Wiki履歴を圧縮する
-  setting_feeds_limit: フィード内容の上限
+  setting_feeds_limit: Atomフィードの項目数の上限
   setting_default_projects_public: デフォルトで新しいプロジェクトは公開にする
   setting_autofetch_changesets: コミットを自動取得する
   setting_sys_api_enabled: リポジトリ管理用のWebサービスを有効にする
@@ -489,12 +481,12 @@ ja:
   label_issue_plural: チケット
   label_issue_view_all: すべてのチケットを見る
   label_issues_by: "%{value} 別のチケット"
-  label_issue_added: チケットが追加されました
-  label_issue_updated: チケットが更新されました
+  label_issue_added: チケットの追加
+  label_issue_updated: チケットの更新
   label_document: 文書
   label_document_new: 新しい文書
   label_document_plural: 文書
-  label_document_added: 文書が追加されました
+  label_document_added: 文書の追加
   label_role: ロール
   label_role_plural: ロール
   label_role_new: 新しいロール
@@ -566,7 +558,7 @@ ja:
   label_attachment_new: 新しいファイル
   label_attachment_delete: ファイルを削除
   label_attachment_plural: ファイル
-  label_file_added: ファイルが追加されました
+  label_file_added: ファイルの追加
   label_report: レポート
   label_report_plural: レポート
   label_news: ニュース
@@ -574,8 +566,8 @@ ja:
   label_news_plural: ニュース
   label_news_latest: 最新ニュース
   label_news_view_all: すべてのニュースを見る
-  label_news_added: ニュースが追加されました
-  label_news_comment_added: ニュースにコメントが追加されました
+  label_news_added: ニュースの追加
+  label_news_comment_added: ニュースへのコメント追加
   label_settings: 設定
   label_overview: 概要
   label_version: バージョン
@@ -605,7 +597,7 @@ ja:
   label_total: 合計
   label_permissions: 権限
   label_current_status: 現在のステータス
-  label_new_statuses_allowed: ステータスの移行先
+  label_new_statuses_allowed: 遷移できるステータス
   label_all: すべて
   label_none: なし
   label_nobody: 無記名
@@ -748,7 +740,7 @@ ja:
   label_message_plural: メッセージ
   label_message_last: 最新のメッセージ
   label_message_new: 新しいメッセージ
-  label_message_posted: メッセージが追加されました
+  label_message_posted: メッセージの追加
   label_reply_plural: 返答
   label_send_information: アカウント情報をユーザーに送信
   label_year: 年
@@ -809,8 +801,8 @@ ja:
   label_ascending: 昇順
   label_descending: 降順
   label_date_from_to: "%{start}から%{end}まで"
-  label_wiki_content_added: Wikiページが追加されました
-  label_wiki_content_updated: Wikiページが更新されました
+  label_wiki_content_added: Wikiページの追加
+  label_wiki_content_updated: Wikiページの更新
   label_group: グループ
   label_group_plural: グループ
   label_group_new: 新しいグループ
@@ -894,7 +886,7 @@ ja:
 
   field_active: 有効
 
-  text_select_mail_notifications: どのメール通知を送信するか、アクションを選択してください。
+  text_select_mail_notifications: メール通知の送信対象とする操作を選択してください。
   text_regexp_info: 例) ^[A-Z0-9]+$
   text_min_max_length_info: 0だと無制限になります
   text_project_destroy_confirmation: 本当にこのプロジェクトと関連データを削除しますか?
@@ -995,9 +987,9 @@ ja:
   label_role_anonymous: 匿名ユーザー
   label_role_non_member: 非メンバー
 
-  label_issue_note_added: 注記が追加されました
-  label_issue_status_updated: ステータスが更新されました
-  label_issue_priority_updated: 優先度が更新されました
+  label_issue_note_added: 注記の追加
+  label_issue_status_updated: ステータスの更新
+  label_issue_priority_updated: 優先度の更新
   label_issues_visibility_own: 作成者か担当者であるチケット
   field_issues_visibility: 表示できるチケット
   label_issues_visibility_all: すべてのチケット
@@ -1136,6 +1128,7 @@ ja:
   setting_force_default_language_for_anonymous: 匿名ユーザーに既定の言語を強制
   setting_force_default_language_for_loggedin: ログインユーザーに既定の言語を強制
   label_custom_field_select_type: カスタムフィールドを追加するオブジェクトを選択してください
+  label_issue_assigned_to_updated: 担当者の更新
   label_check_for_updates: アップデートを確認
   label_latest_compatible_version: 互換性のある最新バージョン
   label_unknown_plugin: 不明なプラグイン
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 03129ac..86abd21 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -1156,6 +1156,7 @@ ko:
   setting_force_default_language_for_anonymous: 익명 사용자의 기본 언어 강제
   setting_force_default_language_for_loggedin: 로그인 사용자의 기본 언어 강제
   label_custom_field_select_type: 사용자 정의 필드에 추가할 대상을 선택해주세요.
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index da6af8a..ec39889 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -1171,6 +1171,7 @@ lt:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/lv.yml b/config/locales/lv.yml
index 328325a..3d5aa84 100644
--- a/config/locales/lv.yml
+++ b/config/locales/lv.yml
@@ -1106,6 +1106,7 @@ lv:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/mk.yml b/config/locales/mk.yml
index f45858d..1e374b3 100644
--- a/config/locales/mk.yml
+++ b/config/locales/mk.yml
@@ -1112,6 +1112,7 @@ mk:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/mn.yml b/config/locales/mn.yml
index 4ea477f..3c3bb95 100644
--- a/config/locales/mn.yml
+++ b/config/locales/mn.yml
@@ -1113,6 +1113,7 @@ mn:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index c07fa30..1d9f327 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -1091,6 +1091,7 @@ nl:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/no.yml b/config/locales/no.yml
index 7839729..9650434 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -1102,6 +1102,7 @@
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 4b623ee..b087d1d 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -1132,6 +1132,7 @@ pl:
   setting_force_default_language_for_loggedin: Wymuś domyślny język dla zalogowanych użytkowników
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Uaktualniono osobę przypisaną
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 10d0407..3035943 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -1131,6 +1131,7 @@ pt-BR:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index 9141227..e6a938d 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -1118,6 +1118,7 @@ pt:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
index e46759e..ef8118d 100644
--- a/config/locales/ro.yml
+++ b/config/locales/ro.yml
@@ -1107,6 +1107,7 @@ ro:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 734f7be..4353aa5 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -1218,6 +1218,7 @@ ru:
   setting_force_default_language_for_anonymous: Не определять язык для анонимных пользователей
   setting_force_default_language_for_loggedin: Не определять язык для зарегистрированных пользователей
   label_custom_field_select_type: Выберите тип объекта для которого будет создано настраиваемое поле
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 4210e17..7e8e239 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -1102,6 +1102,7 @@ sk:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 148f1c8..88e3057 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -1112,6 +1112,7 @@ sl:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index bf19621..a5a66cc 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -1108,6 +1108,7 @@ sq:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/sr-YU.yml b/config/locales/sr-YU.yml
index 959aebd..fdbf05b 100644
--- a/config/locales/sr-YU.yml
+++ b/config/locales/sr-YU.yml
@@ -1114,6 +1114,7 @@ sr-YU:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index d190637..ab68676 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -1113,6 +1113,7 @@ sr:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index b0144a7..3145752 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -1150,6 +1150,7 @@ sv:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 40f5e22..bf7512f 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -1109,6 +1109,7 @@ th:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index 879815c..4ed8efb 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -1121,6 +1121,7 @@ tr:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index 75c6bc6..0e1505d 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -1107,6 +1107,7 @@ uk:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index 15e9dff..dcfa4c1 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -1165,6 +1165,7 @@ vi:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index b229e0c..e000c1f 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -278,7 +278,7 @@
   error_can_not_delete_custom_field: 無法刪除自訂欄位
   error_can_not_delete_tracker: "此追蹤標籤已包含問題,無法被刪除。"
   error_can_not_remove_role: "此角色已被使用,無法將其刪除。"
-  error_can_not_reopen_issue_on_closed_version: '指派給「已結束」版本的問題,無法再將其狀態變更為「進行中」'
+  error_can_not_reopen_issue_on_closed_version: '分派給「已結束」版本的問題,無法再將其狀態變更為「進行中」'
   error_can_not_archive_project: 此專案無法被封存
   error_issue_done_ratios_not_updated: "問題完成百分比未更新。"
   error_workflow_copy_source: '請選擇一個來源問題追蹤標籤或角色'
@@ -298,7 +298,7 @@
   mail_subject_account_activation_request: Redmine 帳號啟用需求通知
   mail_body_account_activation_request: "有位新用戶 (%{value}) 已經完成註冊,正等候您的審核:"
   mail_subject_reminder: "您有 %{count} 個問題即將到期 (%{days})"
-  mail_body_reminder: "%{count} 個指派給您的問題,將於 %{days} 天之內到期:"
+  mail_body_reminder: "%{count} 個分派給您的問題,將於 %{days} 天之內到期:"
   mail_subject_wiki_content_added: "'%{id}' wiki 頁面已被新增"
   mail_body_wiki_content_added: "此 '%{id}' wiki 頁面已被 %{author} 新增。"
   mail_subject_wiki_content_updated: "'%{id}' wiki 頁面已被更新"
@@ -337,7 +337,7 @@
   field_tracker: 追蹤標籤
   field_subject: 主旨
   field_due_date: 完成日期
-  field_assigned_to: 分派給
+  field_assigned_to: 被分派者
   field_priority: 優先權
   field_fixed_version: 版本
   field_user: 用戶
@@ -399,8 +399,8 @@
   field_group_by: 結果分組方式
   field_sharing: 共用
   field_parent_issue: 父問題
-  field_member_of_group: "被指派者的群組"
-  field_assigned_to_role: "被指派者的角色"
+  field_member_of_group: "被分派者的群組"
+  field_assigned_to_role: "被分派者的角色"
   field_text: 內容文字
   field_visible: 可被看見
   field_warn_on_leaving_unsaved: "提醒我將要離開的頁面中尚有未儲存的資料"
@@ -469,7 +469,7 @@
   setting_repository_log_display_limit: 修訂版顯示數目之最大值
   setting_openid: 允許使用 OpenID 登入與註冊
   setting_password_min_length: 密碼最小長度
-  setting_new_project_user_role_id: 管理者以外之用戶建立新專案時,將被指派的角色
+  setting_new_project_user_role_id: 管理者以外之用戶建立新專案時,將被分派的角色
   setting_default_projects_modules: 新專案預設啟用的模組
   setting_issue_done_ratio: 計算問題完成百分比之方式
   setting_issue_done_ratio_issue_field: 依據問題完成百分比欄位
@@ -481,7 +481,7 @@
   setting_commit_logtime_enabled: 啟用認可中的時間記錄
   setting_commit_logtime_activity_id: 時間記錄對應的活動
   setting_gantt_items_limit: 甘特圖中項目顯示數量的最大值
-  setting_issue_group_assignment: 允許問題被指派至群組
+  setting_issue_group_assignment: 允許問題被分派至群組
   setting_default_issue_start_date_to_creation_date: 設定新問題的起始日期為今天的日期
   setting_commit_cross_project_ref: 允許關聯並修正其他專案的問題
   setting_unsubscribe: 允許用戶取消註冊(刪除帳戶)
@@ -593,6 +593,7 @@
   label_issue_updated: 問題已更新
   label_issue_note_added: 筆記已新增
   label_issue_status_updated: 狀態已更新
+  label_issue_assigned_to_updated: 被分派者已更新
   label_issue_priority_updated: 優先權已更新
   label_document: 文件
   label_document_new: 建立新文件
@@ -901,7 +902,7 @@
   label_user_mail_option_selected: "只提醒我所選擇專案中的事件..."
   label_user_mail_option_none: "取消提醒"
   label_user_mail_option_only_my_events: "只提醒我觀察中或參與中的事物"
-  label_user_mail_option_only_assigned: "只提醒我被指派的事物"
+  label_user_mail_option_only_assigned: "只提醒我被分派的事物"
   label_user_mail_option_only_owner: "只提醒我作為擁有者的事物"
   label_user_mail_no_self_notified: "不提醒我自己所做的變更"
   label_registration_activation_by_email: 透過電子郵件啟用帳戶
@@ -956,10 +957,10 @@
   label_principal_search: "搜尋用戶或群組:"
   label_user_search: "搜尋用戶:"
   label_additional_workflow_transitions_for_author: 用戶為作者時額外允許的流程轉換
-  label_additional_workflow_transitions_for_assignee: 用戶為被指定者時額外允許的流程轉換
+  label_additional_workflow_transitions_for_assignee: 用戶為被分派者時額外允許的流程轉換
   label_issues_visibility_all: 所有問題
   label_issues_visibility_public: 所有非私人問題
-  label_issues_visibility_own: 使用者所建立的或被指派的問題
+  label_issues_visibility_own: 使用者所建立的或被分派的問題
   label_git_report_last_commit: 報告最後認可的文件和目錄
   label_parent_revision: 父項
   label_child_revision: 子項
@@ -979,7 +980,7 @@
   label_attribute_of_project: "專案是 %{name}"
   label_attribute_of_issue: "問題是 %{name}"
   label_attribute_of_author: "作者是 %{name}"
-  label_attribute_of_assigned_to: "被指派者是 %{name}"
+  label_attribute_of_assigned_to: "被分派者是 %{name}"
   label_attribute_of_user: "用戶是 %{name}"
   label_attribute_of_fixed_version: "版本是 %{name}"
   label_cross_project_descendants: 與子專案共用
@@ -1094,10 +1095,10 @@
   text_issue_added: "問題 %{id} 已被 %{author} 通報。"
   text_issue_updated: "問題 %{id} 已被 %{author} 更新。"
   text_wiki_destroy_confirmation: 您確定要刪除這個 wiki 和其中的所有內容?
-  text_issue_category_destroy_question: "有 (%{count}) 個問題被指派到此分類. 請選擇您想要的動作?"
+  text_issue_category_destroy_question: "有 (%{count}) 個問題被分派到此分類. 請選擇您想要的動作?"
   text_issue_category_destroy_assignments: 移除這些問題的分類
-  text_issue_category_reassign_to: 重新指派這些問題至其它分類
-  text_user_mail_option: "對於那些未被選擇的專案,將只會接收到您正在觀察中,或是參與中的問題通知。(「參與中的問題」包含您建立的或是指派給您的問題)"
+  text_issue_category_reassign_to: 重新分派這些問題至其它分類
+  text_user_mail_option: "對於那些未被選擇的專案,將只會接收到您正在觀察中,或是參與中的問題通知。(「參與中的問題」包含您建立的或是分派給您的問題)"
   text_no_configuration_data: "角色、追蹤標籤、問題狀態與流程尚未被設定完成。\n強烈建議您先載入預設的組態。將預設組態載入之後,您可再變更其中之值。"
   text_load_default_configuration: 載入預設組態
   text_status_changed_by_changeset: "已套用至變更集 %{value}."
diff --git a/config/locales/zh.yml b/config/locales/zh.yml
index d01f011..31de2fd 100644
--- a/config/locales/zh.yml
+++ b/config/locales/zh.yml
@@ -1113,6 +1113,7 @@ zh:
     users
   label_custom_field_select_type: Select the type of object to which the custom field
     is to be attached
+  label_issue_assigned_to_updated: Assignee updated
   label_check_for_updates: Check for updates
   label_latest_compatible_version: Latest compatible version
   label_unknown_plugin: Unknown plugin
diff --git a/config/preinitializer.rb b/config/preinitializer.rb
deleted file mode 100644
index 90f789c..0000000
--- a/config/preinitializer.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-begin
-  require "rubygems"
-  require "bundler"
-rescue LoadError
-  $stderr.puts "Redmine requires Bundler. Please install it with `gem install bundler`."
-  exit 1
-end
-
-if Gem::Version.new(Bundler::VERSION) < Gem::Version.new("1.0.21")
-  $stderr.puts "Redmine requires Bundler 1.0.21 (you're using #{Bundler::VERSION}).\nPlease install a newer version with `gem install bundler`."
-  exit 1
-end
-
-begin
-  ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
-  Bundler.setup
-rescue Bundler::GemNotFound
-  $stderr.puts "Some gems may need to be installed or updated.\nPlease run `bundle install --without development test`."
-  exit 1
-end
diff --git a/config/routes.rb b/config/routes.rb
index 6be563d..7546b6d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -15,7 +15,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-RedmineApp::Application.routes.draw do
+Rails.application.routes.draw do
   root :to => 'welcome#index', :as => 'home'
 
   match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post]
@@ -25,10 +25,10 @@ RedmineApp::Application.routes.draw do
   match 'account/activate', :to => 'account#activate', :via => :get
   get 'account/activation_email', :to => 'account#activation_email', :as => 'activation_email'
 
-  match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put]
-  match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put]
-  match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put]
-  match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put]
+  match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put, :patch]
+  match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put, :patch]
+  match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put, :patch]
+  match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put, :patch]
 
   match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
   match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
@@ -74,7 +74,7 @@ RedmineApp::Application.routes.draw do
   match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
 
   resources :users
-  match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
+  match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => [:put, :patch], :as => 'user_membership'
   match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
   match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
 
@@ -119,7 +119,7 @@ RedmineApp::Application.routes.draw do
       end
     end
     # issue form update
-    match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :post], :as => 'issue_form'
+    match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :patch, :post], :as => 'issue_form'
 
     resources :files, :only => [:index, :new, :create]
 
@@ -157,7 +157,7 @@ RedmineApp::Application.routes.draw do
         post 'rename'
         get 'history'
         get 'diff'
-        match 'preview', :via => [:post, :put]
+        match 'preview', :via => [:post, :put, :patch]
         post 'protect'
         post 'add_attachment'
       end
diff --git a/db/migrate/001_setup.rb b/db/migrate/001_setup.rb
index f1b9c1e..3cea135 100644
--- a/db/migrate/001_setup.rb
+++ b/db/migrate/001_setup.rb
@@ -17,7 +17,10 @@
 
 class Setup < ActiveRecord::Migration
 
-  class User < ActiveRecord::Base; end
+  class User < ActiveRecord::Base
+    attr_protected :id
+  end
+
   # model removed
   class Permission < ActiveRecord::Base; end
 
diff --git a/db/migrate/20100819172912_enable_calendar_and_gantt_modules_where_appropriate.rb b/db/migrate/20100819172912_enable_calendar_and_gantt_modules_where_appropriate.rb
index 59cd400..5bee50e 100644
--- a/db/migrate/20100819172912_enable_calendar_and_gantt_modules_where_appropriate.rb
+++ b/db/migrate/20100819172912_enable_calendar_and_gantt_modules_where_appropriate.rb
@@ -1,6 +1,6 @@
 class EnableCalendarAndGanttModulesWhereAppropriate < ActiveRecord::Migration
   def self.up
-    EnabledModule.where(:name => 'issue_tracking').all.each do |e|
+    EnabledModule.where(:name => 'issue_tracking').each do |e|
       EnabledModule.create(:name => 'calendar', :project_id => e.project_id)
       EnabledModule.create(:name => 'gantt', :project_id => e.project_id)
     end
diff --git a/doc/CHANGELOG b/doc/CHANGELOG
index bb02fad..a51bd62 100644
--- a/doc/CHANGELOG
+++ b/doc/CHANGELOG
@@ -1469,7 +1469,7 @@ It is in v2.5.0.
 * #819: Add a body ID and class to all pages
 * #871: Commit new CSS styles!
 * #3301: Add favicon to base layout
-* #4656: On Issue#show page, clicking on “Add related issue� should focus on the input
+* #4656: On Issue#show page, clicking on "Add related issue" should focus on the input
 * #4896: Project identifier should be a limited field
 * #5084: Filter all isssues by projects
 * #5477: Replace Test::Unit::TestCase with ActiveSupport::TestCase
@@ -2478,7 +2478,7 @@ It is in v2.5.0.
 * Search engines now supports pagination. Results are sorted in reverse chronological order
 * Added "Estimated hours" attribute on issues
 * A category with assigned issue can now be deleted. 2 options are proposed: remove assignments or reassign issues to another category
-* Forum notifications are now also sent to the authors of the thread, even if they don�t watch the board
+* Forum notifications are now also sent to the authors of the thread, even if they don't watch the board
 * Added an application setting to specify the application protocol (http or https) used to generate urls in emails
 * Gantt chart: now starts at the current month by default
 * Gantt chart: month count and zoom factor are automatically saved as user preferences
@@ -2486,7 +2486,7 @@ It is in v2.5.0.
 * Added wiki index by date
 * Added preview on add/edit issue form
 * Emails footer can now be customized from the admin interface (Admin -> Email notifications)
-* Default encodings for repository files can now be set in application settings (used to convert files content and diff to UTF-8 so that they�re properly displayed)
+* Default encodings for repository files can now be set in application settings (used to convert files content and diff to UTF-8 so that they're properly displayed)
 * Calendar: first day of week can now be set in lang files
 * Automatic closing of duplicate issues
 * Added a cross-project issue list
@@ -2498,7 +2498,7 @@ It is in v2.5.0.
 * Added some accesskeys
 * Added "Float" as a custom field format
 * Added basic Theme support
-* Added the ability to set the �done ratio� of issues fixed by commit (Nikolay Solakov)
+* Added the ability to set the "done ratio" of issues fixed by commit (Nikolay Solakov)
 * Added custom fields in issue related mail notifications
 * Email notifications are now sent in plain text and html
 * Gantt chart can now be exported to a graphic file (png). This functionality is only available if RMagick is installed.
@@ -2531,7 +2531,7 @@ It is in v2.5.0.
 * Added Korean translation (Choi Jong Yoon)
 * Fixed: the link to delete issue relations is displayed even if the user is not authorized to delete relations
 * Performance improvement on calendar and gantt
-* Fixed: wiki preview doesn�t work on long entries
+* Fixed: wiki preview doesn't work on long entries
 * Fixed: queries with multiple custom fields return no result
 * Fixed: Can not authenticate user against LDAP if its DN contains non-ascii characters
 * Fixed: URL with ~ broken in wiki formatting
@@ -2542,7 +2542,7 @@ It is in v2.5.0.
 
 * per project forums added
 * added the ability to archive projects
-* added �Watch� functionality on issues. It allows users to receive notifications about issue changes
+* added "Watch" functionality on issues. It allows users to receive notifications about issue changes
 * custom fields for issues can now be used as filters on issue list
 * added per user custom queries
 * commit messages are now scanned for referenced or fixed issue IDs (keywords defined in Admin -> Settings)
@@ -2583,7 +2583,7 @@ It is in v2.5.0.
 * added swedish translation (Thomas Habets)
 * italian translation update (Alessio Spadaro)
 * japanese translation update (Satoru Kurashiki)
-* fixed: error on history atom feed when there�s no notes on an issue change
+* fixed: error on history atom feed when there's no notes on an issue change
 * fixed: error in journalizing an issue with longtext custom fields (Postgresql)
 * fixed: creation of Oracle schema
 * fixed: last day of the month not included in project activity
diff --git a/doc/INSTALL b/doc/INSTALL
index dfa9472..68fd230 100644
--- a/doc/INSTALL
+++ b/doc/INSTALL
@@ -7,7 +7,7 @@ http://www.redmine.org/
 
 == Requirements
 
-* Ruby 1.8.7, 1.9.2, 1.9.3 or 2.0.0
+* Ruby >= 1.9.3
 * RubyGems
 * Bundler >= 1.0.21
 
@@ -30,9 +30,6 @@ Optional:
 3. Configure the database parameters in config/database.yml
    for the "production" environment (default database is MySQL and ruby1.9)
 
-   If you're running Redmine with MySQL and ruby1.8, replace the adapter name
-   with `mysql`
-
 4. Install the required gems by running:
      bundle install --without development test
 
diff --git a/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb b/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb
index fd5e2a6..8e29700 100644
--- a/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb
+++ b/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb
@@ -29,7 +29,7 @@ module Redmine
             send :include, Redmine::Acts::ActivityProvider::InstanceMethods
           end
 
-          options.assert_valid_keys(:type, :permission, :timestamp, :author_key, :find_options)
+          options.assert_valid_keys(:type, :permission, :timestamp, :author_key, :find_options, :scope)
           self.activity_provider_options ||= {}
 
           # One model can provide different event types
@@ -54,7 +54,7 @@ module Redmine
             provider_options = activity_provider_options[event_type]
             raise "#{self.name} can not provide #{event_type} events." if provider_options.nil?
 
-            scope = self
+            scope = (provider_options[:scope] || self)
 
             if from && to
               scope = scope.where("#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to)
@@ -79,7 +79,7 @@ module Redmine
               scope = scope.where(Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym, options))
             end
 
-            scope.all(provider_options[:find_options].dup)
+            scope.to_a
           end
         end
       end
diff --git a/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb b/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
index a816490..e65c68c 100644
--- a/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
+++ b/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
@@ -29,9 +29,8 @@ module Redmine
           attachable_options[:view_permission] = options.delete(:view_permission) || "view_#{self.name.pluralize.underscore}".to_sym
           attachable_options[:delete_permission] = options.delete(:delete_permission) || "edit_#{self.name.pluralize.underscore}".to_sym
 
-          has_many :attachments, options.merge(:as => :container,
-                                               :order => "#{Attachment.table_name}.created_on ASC, #{Attachment.table_name}.id ASC",
-                                               :dependent => :destroy)
+          has_many :attachments, lambda {order("#{Attachment.table_name}.created_on ASC, #{Attachment.table_name}.id ASC")},
+                                 options.merge(:as => :container, :dependent => :destroy)
           send :include, Redmine::Acts::Attachable::InstanceMethods
           before_save :attach_saved_attachments
         end
diff --git a/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb b/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb
index 928e988..f4a8b2b 100644
--- a/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb
+++ b/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb
@@ -27,9 +27,8 @@ module Redmine
           return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
           cattr_accessor :customizable_options
           self.customizable_options = options
-          has_many :custom_values, :as => :customized,
-                                   :include => :custom_field,
-                                   :order => "#{CustomField.table_name}.position",
+          has_many :custom_values, lambda {includes(:custom_field).order("#{CustomField.table_name}.position")},
+                                   :as => :customized,
                                    :dependent => :delete_all,
                                    :validate => false
 
@@ -46,7 +45,7 @@ module Redmine
         end
 
         def available_custom_fields
-          CustomField.where("type = '#{self.class.name}CustomField'").sorted.all
+          CustomField.where("type = '#{self.class.name}CustomField'").sorted.to_a
         end
 
         # Sets the values of the object's custom fields
diff --git a/lib/plugins/acts_as_event/lib/acts_as_event.rb b/lib/plugins/acts_as_event/lib/acts_as_event.rb
index b053112..d5105e7 100644
--- a/lib/plugins/acts_as_event/lib/acts_as_event.rb
+++ b/lib/plugins/acts_as_event/lib/acts_as_event.rb
@@ -81,7 +81,7 @@ module Redmine
           end
         end
 
-        # Returns the mail adresses of users that should be notified
+        # Returns the mail addresses of users that should be notified
         def recipients
           notified = project.notified_users
           notified.reject! {|user| !visible?(user)}
diff --git a/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb b/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
index 0d4b3cc..8cd907b 100644
--- a/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
+++ b/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
@@ -31,6 +31,7 @@ module Redmine
         # * :permission - permission required to search the model (default to :view_"objects")
         def acts_as_searchable(options = {})
           return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods)
+          options.assert_valid_keys(:columns, :project_key, :date_column, :order_column, :search_custom_fields, :permission, :scope)
 
           cattr_accessor :searchable_options
           self.searchable_options = options
@@ -70,7 +71,7 @@ module Redmine
             # TODO: make user an argument
             user = User.current
             tokens = [] << tokens unless tokens.is_a?(Array)
-            projects = [] << projects unless projects.nil? || projects.is_a?(Array)
+            projects = [] << projects if projects.is_a?(Project)
 
             limit_options = {}
             limit_options[:limit] = options[:limit] if options[:limit]
@@ -100,7 +101,10 @@ module Redmine
 
             tokens_conditions = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort]
 
-            scope = self.scoped
+            scope = (searchable_options[:scope] || self)
+            if scope.is_a? Proc
+              scope = scope.call
+            end
             project_conditions = []
             if searchable_options.has_key?(:permission)
               project_conditions << Project.allowed_to_condition(user, searchable_options[:permission] || :view_project)
@@ -118,10 +122,11 @@ module Redmine
             results_count = 0
 
             scope = scope.
-              includes(searchable_options[:include]).
+              joins(searchable_options[:include]).
               order("#{searchable_options[:order_column]} " + (options[:before] ? 'DESC' : 'ASC')).
               where(project_conditions).
-              where(tokens_conditions)
+              where(tokens_conditions).
+              uniq
 
             results_count = scope.count
 
@@ -129,7 +134,7 @@ module Redmine
             if options[:offset]
               scope_with_limit = scope_with_limit.where("#{searchable_options[:date_column]} #{options[:before] ? '<' : '>'} ?", options[:offset])
             end
-            results = scope_with_limit.all
+            results = scope_with_limit.to_a
 
             [results, results_count]
           end
diff --git a/lib/plugins/acts_as_tree/lib/active_record/acts/tree.rb b/lib/plugins/acts_as_tree/lib/active_record/acts/tree.rb
index 34fa345..c078e7e 100644
--- a/lib/plugins/acts_as_tree/lib/active_record/acts/tree.rb
+++ b/lib/plugins/acts_as_tree/lib/active_record/acts/tree.rb
@@ -44,7 +44,7 @@ module ActiveRecord
           configuration.update(options) if options.is_a?(Hash)
 
           belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]
-          has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => configuration[:dependent]
+          has_many :children, lambda {order(configuration[:order])}, :class_name => name, :foreign_key => configuration[:foreign_key], :dependent => configuration[:dependent]
 
           scope :roots, lambda {
                           where("#{configuration[:foreign_key]} IS NULL").
diff --git a/lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb b/lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
index e31026d..19af8e5 100644
--- a/lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
+++ b/lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
@@ -68,7 +68,7 @@ module Redmine
         end
 
         def notified_watchers
-          notified = watcher_users.active
+          notified = watcher_users.active.to_a
           notified.reject! {|user| user.mail.blank? || user.mail_notification == 'none'}
           if respond_to?(:visible?)
             notified.reject! {|user| !visible?(user)}
diff --git a/lib/redcloth3.rb b/lib/redcloth3.rb
index 7e9097e..e111450 100644
--- a/lib/redcloth3.rb
+++ b/lib/redcloth3.rb
@@ -133,7 +133,7 @@
 #
 # == Adding Tables
 #
-# In Textile, simple tables can be added by seperating each column by
+# In Textile, simple tables can be added by separating each column by
 # a pipe.
 #
 #     |a|simple|table|row|
diff --git a/lib/redmine.rb b/lib/redmine.rb
index 2e97b04..9fad74f 100644
--- a/lib/redmine.rb
+++ b/lib/redmine.rb
@@ -63,12 +63,7 @@ require 'redmine/themes'
 require 'redmine/hook'
 require 'redmine/plugin'
 
-if RUBY_VERSION < '1.9'
-  require 'fastercsv'
-else
-  require 'csv'
-  FCSV = CSV
-end
+require 'csv'
 
 Redmine::Scm::Base.add "Subversion"
 Redmine::Scm::Base.add "Darcs"
diff --git a/lib/redmine/access_control.rb b/lib/redmine/access_control.rb
index 68de569..2135950 100644
--- a/lib/redmine/access_control.rb
+++ b/lib/redmine/access_control.rb
@@ -58,9 +58,11 @@ module Redmine
         if action.is_a?(Symbol)
           perm = permission(action)
           !perm.nil? && perm.read?
-        else
+        elsif action.is_a?(Hash)
           s = "#{action[:controller]}/#{action[:action]}"
           permissions.detect {|p| p.actions.include?(s) && p.read?}.present?
+        else
+          raise ArgumentError.new("Symbol or a Hash expected, #{action.class.name} given: #{action}")
         end
       end
 
diff --git a/lib/redmine/codeset_util.rb b/lib/redmine/codeset_util.rb
index 45a5c35..bb1f972 100644
--- a/lib/redmine/codeset_util.rb
+++ b/lib/redmine/codeset_util.rb
@@ -1,160 +1,71 @@
-if RUBY_VERSION < '1.9'
-  require 'iconv'
-end
 
 module Redmine
   module CodesetUtil
 
     def self.replace_invalid_utf8(str)
       return str if str.nil?
-      if str.respond_to?(:force_encoding)
-        str.force_encoding('UTF-8')
-        if ! str.valid_encoding?
-          str = str.encode("US-ASCII", :invalid => :replace,
-                :undef => :replace, :replace => '?').encode("UTF-8")
-        end
-      elsif RUBY_PLATFORM == 'java'
-        begin
-          ic = Iconv.new('UTF-8', 'UTF-8')
-          str = ic.iconv(str)
-        rescue
-          str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
-        end
-      else
-        ic = Iconv.new('UTF-8', 'UTF-8')
-        txtar = ""
-        begin
-          txtar += ic.iconv(str)
-        rescue Iconv::IllegalSequence
-          txtar += $!.success
-          str = '?' + $!.failed[1,$!.failed.length]
-          retry
-        rescue
-          txtar += $!.success
-        end
-        str = txtar
+      str.force_encoding('UTF-8')
+      if ! str.valid_encoding?
+        str = str.encode("US-ASCII", :invalid => :replace,
+              :undef => :replace, :replace => '?').encode("UTF-8")
       end
       str
     end
 
     def self.to_utf8(str, encoding)
       return str if str.nil?
-      str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
+      str.force_encoding("ASCII-8BIT")
       if str.empty?
-        str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
+        str.force_encoding("UTF-8")
         return str
       end
       enc = encoding.blank? ? "UTF-8" : encoding
-      if str.respond_to?(:force_encoding)
-        if enc.upcase != "UTF-8"
-          str.force_encoding(enc)
-          str = str.encode("UTF-8", :invalid => :replace,
-                :undef => :replace, :replace => '?')
-        else
-          str.force_encoding("UTF-8")
-          if ! str.valid_encoding?
-            str = str.encode("US-ASCII", :invalid => :replace,
-                  :undef => :replace, :replace => '?').encode("UTF-8")
-          end
-        end
-      elsif RUBY_PLATFORM == 'java'
-        begin
-          ic = Iconv.new('UTF-8', enc)
-          str = ic.iconv(str)
-        rescue
-          str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
-        end
+      if enc.upcase != "UTF-8"
+        str.force_encoding(enc)
+        str = str.encode("UTF-8", :invalid => :replace,
+              :undef => :replace, :replace => '?')
       else
-        ic = Iconv.new('UTF-8', enc)
-        txtar = ""
-        begin
-          txtar += ic.iconv(str)
-        rescue Iconv::IllegalSequence
-          txtar += $!.success
-          str = '?' + $!.failed[1,$!.failed.length]
-          retry
-        rescue
-          txtar += $!.success
+        str.force_encoding("UTF-8")
+        if ! str.valid_encoding?
+          str = str.encode("US-ASCII", :invalid => :replace,
+                :undef => :replace, :replace => '?').encode("UTF-8")
         end
-        str = txtar
       end
       str
     end
 
     def self.to_utf8_by_setting(str)
       return str if str.nil?
-      str = self.to_utf8_by_setting_internal(str)
-      if str.respond_to?(:force_encoding)
-        str.force_encoding('UTF-8')
-      end
-      str
+      self.to_utf8_by_setting_internal(str).force_encoding('UTF-8')
     end
 
     def self.to_utf8_by_setting_internal(str)
       return str if str.nil?
-      if str.respond_to?(:force_encoding)
-        str.force_encoding('ASCII-8BIT')
-      end
+      str.force_encoding('ASCII-8BIT')
       return str if str.empty?
       return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
-      if str.respond_to?(:force_encoding)
-        str.force_encoding('UTF-8')
-      end
+      str.force_encoding('UTF-8')
       encodings = Setting.repositories_encodings.split(',').collect(&:strip)
       encodings.each do |encoding|
-        if str.respond_to?(:force_encoding)
-          begin
-            str.force_encoding(encoding)
-            utf8 = str.encode('UTF-8')
-            return utf8 if utf8.valid_encoding?
-          rescue
-            # do nothing here and try the next encoding
-          end
-        else
-          begin
-            return Iconv.conv('UTF-8', encoding, str)
-          rescue Iconv::Failure
-            # do nothing here and try the next encoding
-          end
+        begin
+          str.force_encoding(encoding)
+          utf8 = str.encode('UTF-8')
+          return utf8 if utf8.valid_encoding?
+        rescue
+          # do nothing here and try the next encoding
         end
       end
-      str = self.replace_invalid_utf8(str)
-      if str.respond_to?(:force_encoding)
-        str.force_encoding('UTF-8')
-      end
-      str
+      self.replace_invalid_utf8(str).force_encoding('UTF-8')
     end
 
     def self.from_utf8(str, encoding)
       str ||= ''
-      if str.respond_to?(:force_encoding)
-        str.force_encoding('UTF-8')
-        if encoding.upcase != 'UTF-8'
-          str = str.encode(encoding, :invalid => :replace,
-                           :undef => :replace, :replace => '?')
-        else
-          str = self.replace_invalid_utf8(str)
-        end
-      elsif RUBY_PLATFORM == 'java'
-        begin
-          ic = Iconv.new(encoding, 'UTF-8')
-          str = ic.iconv(str)
-        rescue
-          str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
-        end
+      str.force_encoding('UTF-8')
+      if encoding.upcase != 'UTF-8'
+        str = str.encode(encoding, :invalid => :replace,
+                         :undef => :replace, :replace => '?')
       else
-        ic = Iconv.new(encoding, 'UTF-8')
-        txtar = ""
-        begin
-          txtar += ic.iconv(str)
-        rescue Iconv::IllegalSequence
-          txtar += $!.success
-          str = '?' + $!.failed[1, $!.failed.length]
-          retry
-        rescue
-          txtar += $!.success
-        end
-        str = txtar
+        str = self.replace_invalid_utf8(str)
       end
     end
   end
diff --git a/lib/redmine/configuration.rb b/lib/redmine/configuration.rb
index 09df60d..01abf4e 100644
--- a/lib/redmine/configuration.rb
+++ b/lib/redmine/configuration.rb
@@ -82,10 +82,13 @@ module Redmine
       def load_from_yaml(filename, env)
         yaml = nil
         begin
-          yaml = YAML::load_file(filename)
+          yaml = YAML::load(ERB.new(File.read(filename)).result)
         rescue ArgumentError
           $stderr.puts "Your Redmine configuration file located at #{filename} is not a valid YAML file and could not be loaded."
           exit 1
+        rescue SyntaxError => e
+          $stderr.puts "A syntax error occurred when parsing your Redmine configuration file located at #{filename} with ERB:\n#{e.message}"
+          exit 1
         end
         conf = {}
         if yaml.is_a?(Hash)
diff --git a/lib/redmine/core_ext/active_record.rb b/lib/redmine/core_ext/active_record.rb
index 259da2e..a1135d5 100644
--- a/lib/redmine/core_ext/active_record.rb
+++ b/lib/redmine/core_ext/active_record.rb
@@ -15,35 +15,10 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-module ActiveRecord
-  module FinderMethods
-    def find_ids(*args)
-      find_ids_with_associations
-    end
-
-    private
-  
-    def find_ids_with_associations
-        join_dependency = construct_join_dependency_for_association_find
-        relation = construct_relation_for_association_find_ids(join_dependency)
-        rows = connection.select_all(relation, 'SQL', relation.bind_values)
-        rows.map {|row| row["id"].to_i}
-      rescue ThrowResult
-        []
-    end
-
-    def construct_relation_for_association_find_ids(join_dependency)
-      relation = except(:includes, :eager_load, :preload, :select).select("#{table_name}.id")
-      apply_join_dependency(relation, join_dependency)
-    end
-  end
-end
-
 class DateValidator < ActiveModel::EachValidator
   def validate_each(record, attribute, value)
     before_type_cast = record.attributes_before_type_cast[attribute.to_s]
     if before_type_cast.is_a?(String) && before_type_cast.present?
-      # TODO: #*_date_before_type_cast returns a Mysql::Time with ruby1.8+mysql gem
       unless before_type_cast =~ /\A\d{4}-\d{2}-\d{2}( 00:00:00)?\z/ && value
         record.errors.add attribute, :not_a_date
       end
diff --git a/lib/redmine/core_ext/string/conversions.rb b/lib/redmine/core_ext/string/conversions.rb
index 256f71a..479f47c 100644
--- a/lib/redmine/core_ext/string/conversions.rb
+++ b/lib/redmine/core_ext/string/conversions.rb
@@ -36,13 +36,6 @@ module Redmine #:nodoc:
           s.gsub!(',', '.')
           begin; Kernel.Float(s); rescue; nil; end
         end
-
-        # Object#to_a removed in ruby1.9
-        if RUBY_VERSION > '1.9'
-          def to_a
-            [self.dup]
-          end
-        end
       end
     end
   end
diff --git a/lib/redmine/export/pdf.rb b/lib/redmine/export/pdf.rb
index bd1e64c..a24e560 100644
--- a/lib/redmine/export/pdf.rb
+++ b/lib/redmine/export/pdf.rb
@@ -22,10 +22,6 @@ require 'fpdf/chinese'
 require 'fpdf/japanese'
 require 'fpdf/korean'
 
-if RUBY_VERSION < '1.9'
-  require 'iconv'
-end
-
 module Redmine
   module Export
     module PDF
@@ -121,11 +117,7 @@ module Redmine
 
         # Encodes an UTF-8 string to UTF-16BE
         def to_utf16(str)
-          if str.respond_to?(:encode)
-            str.encode('UTF-16BE')
-          else
-            Iconv.conv('UTF-16BE', 'UTF-8', str)
-          end
+          str.encode('UTF-16BE')
         end
 
         def RDMCell(w ,h=0, txt='', border=0, ln=0, align='', fill=0, link='')
@@ -233,9 +225,9 @@ module Redmine
           #Outline root
           newobj()
           @outlineRoot=self.n
-          out("<</Type /Outlines /First #{n} 0 R");
-          out("/Last #{n+lru[0]} 0 R>>");
-          out('endobj');
+          out("<</Type /Outlines /First #{n} 0 R")
+          out("/Last #{n+lru[0]} 0 R>>")
+          out('endobj')
         end
 
         def putresources()
@@ -246,8 +238,8 @@ module Redmine
         def putcatalog()
           super
           if(@outlines.size > 0)
-            out("/Outlines #{@outlineRoot} 0 R");
-            out('/PageMode /UseOutlines');
+            out("/Outlines #{@outlineRoot} 0 R")
+            out('/PageMode /UseOutlines')
           end
         end
       end
@@ -389,13 +381,13 @@ module Redmine
         base_x = pdf.GetX
         base_y = pdf.GetY
         max_height = issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
-        pdf.Rect(base_x, base_y, table_width, max_height, 'FD');
-        pdf.SetXY(base_x, base_y);
+        pdf.Rect(base_x, base_y, table_width, max_height, 'FD')
+        pdf.SetXY(base_x, base_y)
 
         # write the cells on page
         issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
         issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
-        pdf.SetY(base_y + max_height);
+        pdf.SetY(base_y + max_height)
 
         # rows
         pdf.SetFontStyle('',8)
@@ -475,7 +467,7 @@ module Redmine
           # write the cells on page
           issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
           issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
-          pdf.SetY(base_y + max_height);
+          pdf.SetY(base_y + max_height)
 
           if query.has_column?(:description) && issue.description?
             pdf.SetX(10)
@@ -504,7 +496,7 @@ module Redmine
             pdf.RDMMultiCell(col_widths[i], row_height, column, "T", 'L', 1)
           end
           max_height = (pdf.GetY - base_y) if (pdf.GetY - base_y) > max_height
-          pdf.SetXY(col_x + col_widths[i], base_y);
+          pdf.SetXY(col_x + col_widths[i], base_y)
         end
         return max_height
       end
@@ -783,9 +775,7 @@ module Redmine
         def self.rdm_from_utf8(txt, encoding)
           txt ||= ''
           txt = Redmine::CodesetUtil.from_utf8(txt, encoding)
-          if txt.respond_to?(:force_encoding)
-            txt.force_encoding('ASCII-8BIT')
-          end
+          txt.force_encoding('ASCII-8BIT')
           txt
         end
 
diff --git a/lib/redmine/field_format.rb b/lib/redmine/field_format.rb
index b71a79f..e1387f2 100644
--- a/lib/redmine/field_format.rb
+++ b/lib/redmine/field_format.rb
@@ -603,8 +603,7 @@ module Redmine
         missing = [custom_value.value_was].flatten.reject(&:blank?) - options.map(&:last)
         if missing.any?
           options += target_class.where(:id => missing.map(&:to_i)).map {|o| [o.to_s, o.id.to_s]}
-          #TODO: use #sort_by! when ruby1.8 support is dropped
-          options = options.sort_by(&:first)
+          options.sort_by!(&:first)
         end
         options
       end
diff --git a/lib/redmine/helpers/gantt.rb b/lib/redmine/helpers/gantt.rb
index bc95354..9ebcc92 100644
--- a/lib/redmine/helpers/gantt.rb
+++ b/lib/redmine/helpers/gantt.rb
@@ -167,7 +167,7 @@ module Redmine
             where("child.id IN (?)", ids).
             order("#{Project.table_name}.lft ASC").
             uniq.
-            all
+            to_a
         else
           @projects = []
         end
@@ -338,7 +338,7 @@ module Redmine
           coords = coordinates(version.start_date,
                                version.due_date, version.completed_percent,
                                options[:zoom])
-          label = "#{h version} #{h version.completed_percent.to_i.to_s}%"
+          label = "#{h(version)} #{h(version.completed_percent.to_f.round)}%"
           label = h("#{version.project} -") + label unless @project && @project == version.project
           case options[:format]
           when :html
diff --git a/lib/redmine/hook.rb b/lib/redmine/hook.rb
index 695baf5..715cbaf 100644
--- a/lib/redmine/hook.rb
+++ b/lib/redmine/hook.rb
@@ -30,12 +30,12 @@ module Redmine
         clear_listeners_instances
       end
 
-      # Returns all the listerners instances.
+      # Returns all the listener instances.
       def listeners
         @@listeners ||= @@listener_classes.collect {|listener| listener.instance}
       end
 
-      # Returns the listeners instances for the given hook.
+      # Returns the listener instances for the given hook.
       def hook_listeners(hook)
         @@hook_listeners[hook] ||= listeners.select {|listener| listener.respond_to?(hook)}
       end
diff --git a/lib/redmine/i18n.rb b/lib/redmine/i18n.rb
index 11be1b6..4c9c716 100644
--- a/lib/redmine/i18n.rb
+++ b/lib/redmine/i18n.rb
@@ -94,7 +94,7 @@ module Redmine
     def languages_options
       ActionController::Base.cache_store.fetch "i18n/languages_options" do
         valid_languages.map {|lang| [ll(lang.to_s, :general_lang_name), lang.to_s]}.sort {|x,y| x.first <=> y.first }
-      end      
+      end
     end
 
     def find_language(lang)
diff --git a/lib/redmine/imap.rb b/lib/redmine/imap.rb
index e164ba8..dc4334c 100644
--- a/lib/redmine/imap.rb
+++ b/lib/redmine/imap.rb
@@ -32,7 +32,7 @@ module Redmine
         imap.uid_search(['NOT', 'SEEN']).each do |uid|
           msg = imap.uid_fetch(uid,'RFC822')[0].attr['RFC822']
           logger.debug "Receiving message #{uid}" if logger && logger.debug?
-          if MailHandler.receive(msg, options)
+          if MailHandler.safe_receive(msg, options)
             logger.debug "Message #{uid} successfully received" if logger && logger.debug?
             if imap_options[:move_on_success]
               imap.uid_copy(uid, imap_options[:move_on_success])
diff --git a/lib/redmine/menu_manager.rb b/lib/redmine/menu_manager.rb
index 18759f2..8dfd95a 100644
--- a/lib/redmine/menu_manager.rb
+++ b/lib/redmine/menu_manager.rb
@@ -193,7 +193,7 @@ module Redmine
       # * Checking the url target (project only)
       # * Checking the conditions of the item
       def allowed_node?(node, user, project)
-        if project && user && !user.allowed_to?(node.url, project)
+        if node.url.is_a?(Hash) && project && user && !user.allowed_to?(node.url, project)
           return false
         end
         if node.condition && !node.condition.call(project)
diff --git a/lib/redmine/notifiable.rb b/lib/redmine/notifiable.rb
index 88ca9d7..41fd736 100644
--- a/lib/redmine/notifiable.rb
+++ b/lib/redmine/notifiable.rb
@@ -12,6 +12,7 @@ module Redmine
       notifications << Notifiable.new('issue_updated')
       notifications << Notifiable.new('issue_note_added', 'issue_updated')
       notifications << Notifiable.new('issue_status_updated', 'issue_updated')
+      notifications << Notifiable.new('issue_assigned_to_updated', 'issue_updated')
       notifications << Notifiable.new('issue_priority_updated', 'issue_updated')
       notifications << Notifiable.new('news_added')
       notifications << Notifiable.new('news_comment_added')
diff --git a/lib/redmine/plugin.rb b/lib/redmine/plugin.rb
index 9f2862c..e26ea91 100644
--- a/lib/redmine/plugin.rb
+++ b/lib/redmine/plugin.rb
@@ -113,6 +113,12 @@ module Redmine #:nodoc:
       @registered_plugins = {}
     end
 
+    # Removes a plugin from the registered plugins
+    # It doesn't unload the plugin
+    def self.unregister(id)
+      @registered_plugins.delete(id)
+    end
+
     # Checks if a plugin is installed
     #
     # @param [String] id name of the plugin
@@ -325,7 +331,7 @@ module Redmine #:nodoc:
     # Associated model(s) must implement the find_events class method.
     # ActiveRecord models can use acts_as_activity_provider as a way to implement this class method.
     #
-    # The following call should return all the scrum events visible by current user that occured in the 5 last days:
+    # The following call should return all the scrum events visible by current user that occurred in the 5 last days:
     #   Meeting.find_events('scrums', User.current, 5.days.ago, Date.today)
     #   Meeting.find_events('scrums', User.current, 5.days.ago, Date.today, :project => foo) # events for project foo only
     #
diff --git a/lib/redmine/pop3.rb b/lib/redmine/pop3.rb
index 3ceeeb4..3c7eb95 100644
--- a/lib/redmine/pop3.rb
+++ b/lib/redmine/pop3.rb
@@ -21,8 +21,20 @@ module Redmine
   module POP3
     class << self
       def check(pop_options={}, options={})
+        if pop_options[:ssl]
+          ssl = true
+          if pop_options[:ssl] == 'force'
+            Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
+          else
+            Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_PEER)
+          end
+        else
+          ssl = false
+        end
+
         host = pop_options[:host] || '127.0.0.1'
-        port = pop_options[:port] || '110'
+        port = pop_options[:port]
+        port ||= ssl ? '995' : '110'
         apop = (pop_options[:apop].to_s == '1')
         delete_unprocessed = (pop_options[:delete_unprocessed].to_s == '1')
 
@@ -36,7 +48,7 @@ module Redmine
             pop_session.each_mail do |msg|
               message = msg.pop
               message_id = (message =~ /^Message-I[dD]: (.*)/ ? $1 : '').strip
-              if MailHandler.receive(message, options)
+              if MailHandler.safe_receive(message, options)
                 msg.delete
                 logger.debug "--> Message #{message_id} processed and deleted from the server" if logger && logger.debug?
               else
diff --git a/lib/redmine/scm/adapters/abstract_adapter.rb b/lib/redmine/scm/adapters/abstract_adapter.rb
index ec168bf..0e60de6 100644
--- a/lib/redmine/scm/adapters/abstract_adapter.rb
+++ b/lib/redmine/scm/adapters/abstract_adapter.rb
@@ -18,17 +18,13 @@
 require 'cgi'
 require 'redmine/scm/adapters'
 
-if RUBY_VERSION < '1.9'
-  require 'iconv'
-end
-
 module Redmine
   module Scm
     module Adapters
       class AbstractAdapter #:nodoc:
 
         # raised if scm command exited with error, e.g. unknown revision.
-        class ScmCommandAborted < CommandFailed; end
+        class ScmCommandAborted < ::Redmine::Scm::Adapters::CommandFailed; end
 
         class << self
           def client_command
@@ -288,21 +284,12 @@ module Redmine
         def scm_iconv(to, from, str)
           return nil if str.nil?
           return str if to == from
-          if str.respond_to?(:force_encoding)
-            str.force_encoding(from)
-            begin
-              str.encode(to)
-            rescue Exception => err
-              logger.error("failed to convert from #{from} to #{to}. #{err}")
-              nil
-            end
-          else
-            begin
-              Iconv.conv(to, from, str)
-            rescue Iconv::Failure => err
-              logger.error("failed to convert from #{from} to #{to}. #{err}")
-              nil
-            end
+          str.force_encoding(from)
+          begin
+            str.encode(to)
+          rescue Exception => err
+            logger.error("failed to convert from #{from} to #{to}. #{err}")
+            nil
           end
         end
 
diff --git a/lib/redmine/scm/adapters/bazaar_adapter.rb b/lib/redmine/scm/adapters/bazaar_adapter.rb
index 93ac13e..c5e9d12 100644
--- a/lib/redmine/scm/adapters/bazaar_adapter.rb
+++ b/lib/redmine/scm/adapters/bazaar_adapter.rb
@@ -43,10 +43,7 @@ module Redmine
           end
 
           def scm_command_version
-            scm_version = scm_version_from_command_line.dup
-            if scm_version.respond_to?(:force_encoding)
-              scm_version.force_encoding('ASCII-8BIT')
-            end
+            scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT')
             if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
               m[2].scan(%r{\d+}).collect(&:to_i)
             end
@@ -100,7 +97,7 @@ module Redmine
             prefix_utf8 = "#{url}/#{path}".gsub('\\', '/')
             logger.debug "PREFIX: #{prefix_utf8}"
             prefix = scm_iconv(@path_encoding, 'UTF-8', prefix_utf8)
-            prefix.force_encoding('ASCII-8BIT') if prefix.respond_to?(:force_encoding)
+            prefix.force_encoding('ASCII-8BIT')
             re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
             io.each_line do |line|
               next unless line =~ re
diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb
index d1096e7..81b2dfe 100644
--- a/lib/redmine/scm/adapters/cvs_adapter.rb
+++ b/lib/redmine/scm/adapters/cvs_adapter.rb
@@ -43,10 +43,7 @@ module Redmine
           end
 
           def scm_command_version
-            scm_version = scm_version_from_command_line.dup
-            if scm_version.respond_to?(:force_encoding)
-              scm_version.force_encoding('ASCII-8BIT')
-            end
+            scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT')
             if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m)
               m[2].scan(%r{\d+}).collect(&:to_i)
             end
@@ -94,7 +91,7 @@ module Redmine
         def entries(path=nil, identifier=nil, options={})
           logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
           path_locale = scm_iconv(@path_encoding, 'UTF-8', path)
-          path_locale.force_encoding("ASCII-8BIT") if path_locale.respond_to?(:force_encoding)
+          path_locale.force_encoding("ASCII-8BIT")
           entries = Entries.new
           cmd_args = %w|-q rls -e|
           cmd_args << "-D" << time_to_cvstime_rlog(identifier) if identifier
diff --git a/lib/redmine/scm/adapters/darcs_adapter.rb b/lib/redmine/scm/adapters/darcs_adapter.rb
index 3e4d552..e280735 100644
--- a/lib/redmine/scm/adapters/darcs_adapter.rb
+++ b/lib/redmine/scm/adapters/darcs_adapter.rb
@@ -43,10 +43,7 @@ module Redmine
           end
 
           def darcs_binary_version
-            darcsversion = darcs_binary_version_from_command_line.dup
-            if darcsversion.respond_to?(:force_encoding)
-              darcsversion.force_encoding('ASCII-8BIT')
-            end
+            darcsversion = darcs_binary_version_from_command_line.dup.force_encoding('ASCII-8BIT')
             if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)})
               m[2].scan(%r{\d+}).collect(&:to_i)
             end
diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb
index 284a3f4..7a6a590 100644
--- a/lib/redmine/scm/adapters/git_adapter.rb
+++ b/lib/redmine/scm/adapters/git_adapter.rb
@@ -47,10 +47,7 @@ module Redmine
           end
 
           def scm_command_version
-            scm_version = scm_version_from_command_line.dup
-            if scm_version.respond_to?(:force_encoding)
-              scm_version.force_encoding('ASCII-8BIT')
-            end
+            scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT')
             if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
               m[2].scan(%r{\d+}).collect(&:to_i)
             end
@@ -145,10 +142,7 @@ module Redmine
                 type = $1
                 sha  = $2
                 size = $3
-                name = $4
-                if name.respond_to?(:force_encoding)
-                  name.force_encoding(@path_encoding)
-                end
+                name = $4.force_encoding(@path_encoding)
                 full_path = p.empty? ? name : "#{p}/#{name}"
                 n      = scm_iconv('UTF-8', @path_encoding, name)
                 full_p = scm_iconv('UTF-8', @path_encoding, full_path)
diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb
index 881fdc8..c6aa388 100644
--- a/lib/redmine/scm/adapters/mercurial_adapter.rb
+++ b/lib/redmine/scm/adapters/mercurial_adapter.rb
@@ -54,10 +54,7 @@ module Redmine
             # The hg version is expressed either as a
             # release number (eg 0.9.5 or 1.0) or as a revision
             # id composed of 12 hexa characters.
-            theversion = hgversion_from_command_line.dup
-            if theversion.respond_to?(:force_encoding)
-              theversion.force_encoding('ASCII-8BIT')
-            end
+            theversion = hgversion_from_command_line.dup.force_encoding('ASCII-8BIT')
             if m = theversion.match(%r{\A(.*?)((\d+\.)+\d+)})
               m[2].scan(%r{\d+}).collect(&:to_i)
             end
@@ -130,10 +127,7 @@ module Redmine
         def summary
           return @summary if @summary
           hg 'rhsummary' do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
+            output = io.read.force_encoding('UTF-8')
             begin
               @summary = parse_xml(output)['rhsummary']
             rescue
@@ -146,10 +140,7 @@ module Redmine
           p1 = scm_iconv(@path_encoding, 'UTF-8', path)
           manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)),
                         CGI.escape(without_leading_slash(p1.to_s))) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
+            output = io.read.force_encoding('UTF-8')
             begin
               parse_xml(output)['rhmanifest']['repository']['manifest']
             rescue
@@ -193,10 +184,7 @@ module Redmine
           hg_args << '--limit' << options[:limit] if options[:limit]
           hg_args << hgtarget(path) unless path.blank?
           log = hg(*hg_args) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
+            output = io.read.force_encoding('UTF-8')
             begin
               # Mercurial < 1.5 does not support footer template for '</log>'
               parse_xml("#{output}</log>")['log']
@@ -278,7 +266,7 @@ module Redmine
           blame = Annotate.new
           hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
             io.each_line do |line|
-              line.force_encoding('ASCII-8BIT') if line.respond_to?(:force_encoding)
+              line.force_encoding('ASCII-8BIT')
               next unless line =~ %r{^([^:]+)\s(\d+)\s([0-9a-f]+):\s(.*)$}
               r = Revision.new(:author => $1.strip, :revision => $2, :scmid => $3,
                                :identifier => $3)
diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb
index fcc9be9..30ebc0c 100644
--- a/lib/redmine/scm/adapters/subversion_adapter.rb
+++ b/lib/redmine/scm/adapters/subversion_adapter.rb
@@ -46,10 +46,7 @@ module Redmine
           end
 
           def svn_binary_version
-            scm_version = scm_version_from_command_line.dup
-            if scm_version.respond_to?(:force_encoding)
-              scm_version.force_encoding('ASCII-8BIT')
-            end
+            scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT')
             if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
               m[2].scan(%r{\d+}).collect(&:to_i)
             end
@@ -66,10 +63,7 @@ module Redmine
           cmd << credentials_string
           info = nil
           shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
+            output = io.read.force_encoding('UTF-8')
             begin
               doc = parse_xml(output)
               # root_url = doc.elements["info/entry/repository/root"].text
@@ -98,10 +92,7 @@ module Redmine
           cmd = "#{self.class.sq_bin} list --xml #{target(path)}@#{identifier}"
           cmd << credentials_string
           shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
+            output = io.read.force_encoding('UTF-8')
             begin
               doc = parse_xml(output)
               each_xml_element(doc['lists']['list'], 'entry') do |entry|
@@ -141,10 +132,7 @@ module Redmine
           cmd << credentials_string
           properties = {}
           shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
+            output = io.read.force_encoding('UTF-8')
             begin
               doc = parse_xml(output)
               each_xml_element(doc['properties']['target'], 'property') do |property|
@@ -168,10 +156,7 @@ module Redmine
           cmd << " --limit #{options[:limit].to_i}" if options[:limit]
           cmd << ' ' + target(path)
           shellout(cmd) do |io|
-            output = io.read
-            if output.respond_to?(:force_encoding)
-              output.force_encoding('UTF-8')
-            end
+            output = io.read.force_encoding('UTF-8')
             begin
               doc = parse_xml(output)
               each_xml_element(doc['log'], 'logentry') do |logentry|
diff --git a/lib/redmine/unified_diff.rb b/lib/redmine/unified_diff.rb
index ee4ac69..b402059 100644
--- a/lib/redmine/unified_diff.rb
+++ b/lib/redmine/unified_diff.rb
@@ -199,28 +199,10 @@ module Redmine
         while starting < max && line_left[starting] == line_right[starting]
           starting += 1
         end
-        if (! "".respond_to?(:force_encoding)) && starting < line_left.size
-          while line_left[starting].ord.between?(128, 191) && starting > 0
-            starting -= 1
-          end
-        end
         ending = -1
         while ending >= -(max - starting) && (line_left[ending] == line_right[ending])
           ending -= 1
         end
-        if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size)
-          while line_left[ending].ord.between?(128, 255) && ending < -1
-            if line_left[ending].ord.between?(128, 191)
-              if line_left[ending + 1].ord.between?(128, 191)
-                ending += 1
-              else
-                break
-              end
-            else
-              ending += 1
-            end
-          end
-        end
         unless starting == 0 && ending == -1
           [starting, ending]
         end
@@ -279,7 +261,7 @@ module Redmine
 
     def line_to_html(line, offsets)
       html = line_to_html_raw(line, offsets)
-      html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
+      html.force_encoding('UTF-8')
       html
     end
 
diff --git a/lib/redmine/version.rb b/lib/redmine/version.rb
index a9f3566..83eb763 100644
--- a/lib/redmine/version.rb
+++ b/lib/redmine/version.rb
@@ -10,7 +10,7 @@ module Redmine
     # * official release: nil
     # * stable branch:    stable
     # * trunk:            devel
-    BRANCH = 'stable'
+    BRANCH = 'devel'
 
     # Retrieves the revision from the working copy
     def self.revision
diff --git a/lib/redmine/views/labelled_form_builder.rb b/lib/redmine/views/labelled_form_builder.rb
index 08ccf5f..7437416 100644
--- a/lib/redmine/views/labelled_form_builder.rb
+++ b/lib/redmine/views/labelled_form_builder.rb
@@ -39,17 +39,17 @@ class Redmine::Views::LabelledFormBuilder < ActionView::Helpers::FormBuilder
   end
 
   def time_zone_select(field, priority_zones = nil, options = {}, html_options = {})
-        label_for_field(field, options) + super(field, priority_zones, options, html_options.except(:label)).html_safe
+    label_for_field(field, options) + super(field, priority_zones, options, html_options.except(:label)).html_safe
   end
 
   # Returns a label tag for the given field
   def label_for_field(field, options = {})
-      return ''.html_safe if options.delete(:no_label)
-      text = options[:label].is_a?(Symbol) ? l(options[:label]) : options[:label]
-      text ||= l(("field_" + field.to_s.gsub(/\_id$/, "")).to_sym)
-      text += @template.content_tag("span", " *", :class => "required") if options.delete(:required)
-      @template.content_tag("label", text.html_safe,
-                                     :class => (@object && @object.errors[field].present? ? "error" : nil),
-                                     :for => (@object_name.to_s + "_" + field.to_s))
+    return ''.html_safe if options.delete(:no_label)
+    text = options[:label].is_a?(Symbol) ? l(options[:label]) : options[:label]
+    text ||= l(("field_" + field.to_s.gsub(/\_id$/, "")).to_sym)
+    text += @template.content_tag("span", " *", :class => "required") if options.delete(:required)
+    @template.content_tag("label", text.html_safe,
+                                   :class => (@object && @object.errors[field].present? ? "error" : nil),
+                                   :for => (@object_name.to_s + "_" + field.to_s))
   end
 end
diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb
index 3bf483d..284cdc9 100644
--- a/lib/redmine/wiki_formatting.rb
+++ b/lib/redmine/wiki_formatting.rb
@@ -111,20 +111,20 @@ module Redmine
                       (?=<|\s|$)
                      }x unless const_defined?(:AUTO_LINK_RE)
 
-      # Destructively remplaces urls into clickable links
+      # Destructively replaces urls into clickable links
       def auto_link!(text)
         text.gsub!(AUTO_LINK_RE) do
           all, leading, proto, url, post = $&, $1, $2, $3, $6
           if leading =~ /<a\s/i || leading =~ /![<>=]?/
-            # don't replace URL's that are already linked
-            # and URL's prefixed with ! !> !< != (textile images)
+            # don't replace URLs that are already linked
+            # and URLs prefixed with ! !> !< != (textile images)
             all
           else
-            # Idea below : an URL with unbalanced parethesis and
+            # Idea below : an URL with unbalanced parenthesis and
             # ending by ')' is put into external parenthesis
             if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) )
-              url=url[0..-2] # discard closing parenth from url
-              post = ")"+post # add closing parenth to post
+              url=url[0..-2] # discard closing parenthesis from url
+              post = ")"+post # add closing parenthesis to post
             end
             content = proto + url
             href = "#{proto=="www."?"http://www.":proto}#{url}"
@@ -133,7 +133,7 @@ module Redmine
         end
       end
 
-      # Destructively remplaces email addresses into clickable links
+      # Destructively replaces email addresses into clickable links
       def auto_mailto!(text)
         text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
           mail = $1
diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake
index fbc4d56..857cc23 100644
--- a/lib/tasks/ci.rake
+++ b/lib/tasks/ci.rake
@@ -1,4 +1,4 @@
-desc "Run the Continous Integration tests for Redmine"
+desc "Run the Continuous Integration tests for Redmine"
 task :ci do
   # RAILS_ENV and ENV[] can diverge so force them both to test
   ENV['RAILS_ENV'] = 'test'
@@ -33,7 +33,7 @@ namespace :ci do
     else
       Rake::Task["test"].invoke
     end
-    # Rake::Task["test:ui"].invoke if RUBY_VERSION >= '1.9.3'
+    # Rake::Task["test:ui"].invoke
   end
 
   desc "Finish the build"
@@ -52,7 +52,7 @@ file 'config/database.yml' do
 
   case database
   when 'mysql'
-    dev_conf =  {'adapter' => (RUBY_VERSION >= '1.9' ? 'mysql2' : 'mysql'),
+    dev_conf =  {'adapter' => 'mysql2',
                  'database' => dev_db_name, 'host' => 'localhost',
                  'encoding' => 'utf8'}
     if ENV['RUN_ON_NOT_OFFICIAL']
diff --git a/lib/tasks/ciphering.rake b/lib/tasks/ciphering.rake
index 6443eeb..fefe3ac 100644
--- a/lib/tasks/ciphering.rake
+++ b/lib/tasks/ciphering.rake
@@ -21,7 +21,7 @@ namespace :db do
   task :encrypt => :environment do
     unless (Repository.encrypt_all(:password) &&
       AuthSource.encrypt_all(:account_password))
-      raise "Some objects could not be saved after encryption, update was rollback'ed."
+      raise "Some objects could not be saved after encryption, update was rolled back."
     end
   end
 
@@ -29,7 +29,7 @@ namespace :db do
   task :decrypt => :environment do
     unless (Repository.decrypt_all(:password) &&
       AuthSource.decrypt_all(:account_password))
-      raise "Some objects could not be saved after decryption, update was rollback'ed."
+      raise "Some objects could not be saved after decryption, update was rolled back."
     end
   end
 end
diff --git a/lib/tasks/email.rake b/lib/tasks/email.rake
index 84eb279..95a19e4 100644
--- a/lib/tasks/email.rake
+++ b/lib/tasks/email.rake
@@ -55,7 +55,9 @@ Examples:
 END_DESC
 
     task :read => :environment do
-      MailHandler.receive(STDIN.read, MailHandler.extract_options_from_env(ENV))
+      Mailer.with_synched_deliveries do
+        MailHandler.receive(STDIN.read, MailHandler.extract_options_from_env(ENV))
+      end
     end
 
     desc <<-END_DESC
@@ -122,7 +124,9 @@ END_DESC
                       :move_on_success => ENV['move_on_success'],
                       :move_on_failure => ENV['move_on_failure']}
 
-      Redmine::IMAP.check(imap_options, MailHandler.extract_options_from_env(ENV))
+      Mailer.with_synched_deliveries do
+        Redmine::IMAP.check(imap_options, MailHandler.extract_options_from_env(ENV))
+      end
     end
 
     desc <<-END_DESC
@@ -134,6 +138,7 @@ Available POP3 options:
   username=USERNAME        POP3 account
   password=PASSWORD        POP3 password
   apop=1                   use APOP authentication (default: false)
+  ssl=SSL                  Use SSL? (default: false)
   delete_unprocessed=1     delete messages that could not be processed
                            successfully from the server (default
                            behaviour is to leave them on the server)
@@ -145,11 +150,14 @@ END_DESC
       pop_options  = {:host => ENV['host'],
                       :port => ENV['port'],
                       :apop => ENV['apop'],
+                      :ssl => ENV['ssl'],
                       :username => ENV['username'],
                       :password => ENV['password'],
                       :delete_unprocessed => ENV['delete_unprocessed']}
 
-      Redmine::POP3.check(pop_options, MailHandler.extract_options_from_env(ENV))
+      Mailer.with_synched_deliveries do
+        Redmine::POP3.check(pop_options, MailHandler.extract_options_from_env(ENV))
+      end
     end
 
     desc "Send a test email to the user with the provided login name"
diff --git a/lib/tasks/locales.rake b/lib/tasks/locales.rake
index 6311d6a..7d2ecfe 100644
--- a/lib/tasks/locales.rake
+++ b/lib/tasks/locales.rake
@@ -68,9 +68,6 @@ namespace :locales do
   desc <<-END_DESC
 Removes a translation string from all locale file (only works for top-level childless non-multiline keys, probably doesn\'t work on windows).
 
-This task does not work on Ruby 1.8.6.
-You need to use Ruby 1.8.7 or later.
-
 Options:
   key=key_1,key_2    Comma-separated list of keys to delete
   skip=en,de         Comma-separated list of locale files to ignore (filename without extension)
diff --git a/lib/tasks/migrate_from_mantis.rake b/lib/tasks/migrate_from_mantis.rake
index 2d5f66f..1040dbb 100644
--- a/lib/tasks/migrate_from_mantis.rake
+++ b/lib/tasks/migrate_from_mantis.rake
@@ -18,7 +18,6 @@
 desc 'Mantis migration script'
 
 require 'active_record'
-require 'iconv' if RUBY_VERSION < '1.9'
 require 'pp'
 
 namespace :redmine do
@@ -452,12 +451,7 @@ task :migrate_from_mantis => :environment do
     end
 
     def self.encode(text)
-      if RUBY_VERSION < '1.9'
-        @ic ||= Iconv.new('UTF-8', @charset)
-        @ic.iconv text
-      else
-        text.to_s.force_encoding(@charset).encode('UTF-8')
-      end
+      text.to_s.force_encoding(@charset).encode('UTF-8')
     end
   end
 
diff --git a/lib/tasks/migrate_from_trac.rake b/lib/tasks/migrate_from_trac.rake
index 74272b6..d1a3873 100644
--- a/lib/tasks/migrate_from_trac.rake
+++ b/lib/tasks/migrate_from_trac.rake
@@ -16,7 +16,6 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require 'active_record'
-require 'iconv' if RUBY_VERSION < '1.9'
 require 'pp'
 
 namespace :redmine do
@@ -155,7 +154,7 @@ namespace :redmine do
           attachment_type = read_attribute(:type)
           #replace exotic characters with their hex representation to avoid invalid filenames
           trac_file = filename.gsub( /[^a-zA-Z0-9\-_\.!~*']/n ) do |x|
-            codepoint = RUBY_VERSION < '1.9' ? x[0] : x.codepoints.to_a[0]
+            codepoint = x.codepoints.to_a[0]
             sprintf('%%%02x', codepoint)
           end
           "#{TracMigrate.trac_attachments_directory}/#{attachment_type}/#{id}/#{trac_file}"
@@ -327,9 +326,9 @@ namespace :redmine do
         # We would like to convert the Code highlighting too
         # This will go into the next line.
         shebang_line = false
-        # Reguar expression for start of code
+        # Regular expression for start of code
         pre_re = /\{\{\{/
-        # Code hightlighing...
+        # Code highlighting...
         shebang_re = /^\#\!([a-z]+)/
         # Regular expression for end of code
         pre_end_re = /\}\}\}/
@@ -715,12 +714,7 @@ namespace :redmine do
       end
 
       def self.encode(text)
-        if RUBY_VERSION < '1.9'
-          @ic ||= Iconv.new('UTF-8', @charset)
-          @ic.iconv text
-        else
-          text.to_s.force_encoding(@charset).encode('UTF-8')
-        end
+        text.to_s.force_encoding(@charset).encode('UTF-8')
       end
     end
 
@@ -781,4 +775,3 @@ namespace :redmine do
     end
   end
 end
-
diff --git a/lib/tasks/redmine.rake b/lib/tasks/redmine.rake
index c8d35af..c9ee517 100644
--- a/lib/tasks/redmine.rake
+++ b/lib/tasks/redmine.rake
@@ -68,7 +68,8 @@ DESC
     tables = ActiveRecord::Base.connection.tables.sort - %w(schema_migrations plugin_schema_info)
 
     if (tables - target_tables).any?
-      abort "The following table(s) are missing from the target database: #{(tables - target_tables).join(', ')}"
+      list = (tables - target_tables).map {|table| "* #{table}"}.join("\n")
+      abort "The following table(s) are missing from the target database:\n#{list}"
     end
 
     tables.each do |table_name|
diff --git a/lib/tasks/testing.rake b/lib/tasks/testing.rake
index cfb8e77..9eb7ff7 100644
--- a/lib/tasks/testing.rake
+++ b/lib/tasks/testing.rake
@@ -26,7 +26,7 @@ namespace :test do
   namespace :scm do
     namespace :setup do
       desc "Creates directory for test repositories"
-      task :create_dir do
+      task :create_dir => :environment do
         FileUtils.mkdir_p Rails.root + '/tmp/test'
       end
 
@@ -51,13 +51,17 @@ namespace :test do
         end
       end
 
+      def extract_tar_gz(prefix)
+        unless File.exists?("tmp/test/#{prefix}_repository")
+          # system "gunzip < test/fixtures/repositories/#{prefix}_repository.tar.gz | tar -xv -C tmp/test"
+          system "tar -xvz -C tmp/test -f test/fixtures/repositories/#{prefix}_repository.tar.gz"
+        end
+      end
+
       (supported_scms - [:subversion, :mercurial]).each do |scm|
         desc "Creates a test #{scm} repository"
         task scm => :create_dir do
-          unless File.exists?("tmp/test/#{scm}_repository")
-            # system "gunzip < test/fixtures/repositories/#{scm}_repository.tar.gz | tar -xv -C tmp/test"
-            system "tar -xvz -C tmp/test -f test/fixtures/repositories/#{scm}_repository.tar.gz"
-          end
+          extract_tar_gz(scm)
         end
       end
 
@@ -66,7 +70,7 @@ namespace :test do
     end
 
     desc "Updates installed test repositories"
-    task :update do
+    task :update => :environment do
       require 'fileutils'
       Dir.glob("tmp/test/*_repository").each do |dir|
         next unless File.basename(dir) =~ %r{^(.+)_repository$} && File.directory?(dir)
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index fdf5c47..38193b8 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -2,7 +2,7 @@
    Copyright (C) 2006-2014  Jean-Philippe Lang */
 
 function checkAll(id, checked) {
-  $('#'+id).find('input[type=checkbox]:enabled').attr('checked', checked);
+  $('#'+id).find('input[type=checkbox]:enabled').prop('checked', checked);
 }
 
 function toggleCheckboxesBySelector(selector) {
@@ -10,7 +10,7 @@ function toggleCheckboxesBySelector(selector) {
   $(selector).each(function(index) {
     if (!$(this).is(':checked')) { all_checked = false; }
   });
-  $(selector).attr('checked', !all_checked);
+  $(selector).prop('checked', !all_checked);
 }
 
 function showAndScrollTo(id, focus) {
@@ -81,13 +81,13 @@ function initFilters() {
   $('#filters-table td.field input[type=checkbox]').each(function() {
     toggleFilter($(this).val());
   });
-  $('#filters-table td.field input[type=checkbox]').live('click', function() {
+  $('#filters-table').on('click', 'td.field input[type=checkbox]', function() {
     toggleFilter($(this).val());
   });
-  $('#filters-table .toggle-multiselect').live('click', function() {
+  $('#filters-table').on('click', '.toggle-multiselect', function() {
     toggleMultiSelect($(this).siblings('select'));
   });
-  $('#filters-table input[type=text]').live('keypress', function(e) {
+  $('#filters-table').on('keypress', 'input[type=text]', function(e) {
     if (e.keyCode == 13) submit_query_form("query_form");
   });
 }
@@ -100,7 +100,7 @@ function addFilter(field, operator, values) {
   } else {
     buildFilterRow(field, operator, values);
   }
-  $('#cb_'+fieldId).attr('checked', true);
+  $('#cb_'+fieldId).prop('checked', true);
   toggleFilter(field);
   $('#add_filter_select').val('').children('option').each(function() {
     if ($(this).attr('value') == field) {
@@ -537,10 +537,10 @@ function initMyPageSortable(list, url) {
 var warnLeavingUnsavedMessage;
 function warnLeavingUnsaved(message) {
   warnLeavingUnsavedMessage = message;
-  $('form').live('submit', function(){
+  $(document).on('submit', 'form', function(){
     $('textarea').removeData('changed');
   });
-  $('textarea').live('change', function(){
+  $(document).on('change', 'textarea', function(){
     $(this).data('changed', 'changed');
   });
   window.onbeforeunload = function(){
@@ -555,12 +555,12 @@ function warnLeavingUnsaved(message) {
 }
 
 function setupAjaxIndicator() {
-  $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) {
+  $(document).bind('ajaxSend', function(event, xhr, settings) {
     if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') {
       $('#ajax-indicator').show();
     }
   });
-  $('#ajax-indicator').bind('ajaxStop', function() {
+  $(document).bind('ajaxStop', function() {
     $('#ajax-indicator').hide();
   });
 }
diff --git a/public/javascripts/context_menu.js b/public/javascripts/context_menu.js
index a3e1545..aee3483 100644
--- a/public/javascripts/context_menu.js
+++ b/public/javascripts/context_menu.js
@@ -31,7 +31,7 @@ function contextMenuClick(event) {
       // a row was clicked, check if the click was on checkbox
       if (target.is('input')) {
         // a checkbox may be clicked
-        if (target.attr('checked')) {
+        if (target.prop('checked')) {
           tr.addClass('context-menu-selection');
         } else {
           tr.removeClass('context-menu-selection');
@@ -180,7 +180,7 @@ function contextMenuIsSelected(tr) {
 }
 
 function contextMenuCheckSelectionBox(tr, checked) {
-  tr.find('input[type=checkbox]').attr('checked', checked);
+  tr.find('input[type=checkbox]').prop('checked', checked);
 }
 
 function contextMenuClearDocumentSelection() {
@@ -207,13 +207,13 @@ function contextMenuInit(url) {
 function toggleIssuesSelection(el) {
   var boxes = $(el).parents('form').find('input[type=checkbox]');
   var all_checked = true;
-  boxes.each(function(){ if (!$(this).attr('checked')) { all_checked = false; } });
+  boxes.each(function(){ if (!$(this).prop('checked')) { all_checked = false; } });
   boxes.each(function(){
     if (all_checked) {
       $(this).removeAttr('checked');
       $(this).parents('tr').removeClass('context-menu-selection');
-    } else if (!$(this).attr('checked')) {
-      $(this).attr('checked', true);
+    } else if (!$(this).prop('checked')) {
+      $(this).prop('checked', true);
       $(this).parents('tr').addClass('context-menu-selection');
     }
   });
diff --git a/public/javascripts/gantt.js b/public/javascripts/gantt.js
index e5f8ab9..664f4a7 100644
--- a/public/javascripts/gantt.js
+++ b/public/javascripts/gantt.js
@@ -165,8 +165,8 @@ function drawGanttHandler() {
   else
     draw_gantt = Raphael(folder);
   setDrawArea();
-  if ($("#draw_progress_line").attr('checked'))
+  if ($("#draw_progress_line").prop('checked'))
     drawGanttProgressLines();
-  if ($("#draw_relations").attr('checked'))
+  if ($("#draw_relations").prop('checked'))
     drawRelations();
 }
diff --git a/public/javascripts/jquery-1.11.1-ui-1.11.0-ujs-3.1.1.js b/public/javascripts/jquery-1.11.1-ui-1.11.0-ujs-3.1.1.js
new file mode 100644
index 0000000..06711bd
--- /dev/null
+++ b/public/javascripts/jquery-1.11.1-ui-1.11.0-ujs-3.1.1.js
@@ -0,0 +1,21 @@
+/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b [...]
+if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&& [...]
+},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.prop [...]
+
+/*! jQuery UI - v1.11.0 - 2014-06-26
+* http://jqueryui.com
+* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js,  [...]
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap=#"+a+"]")[0],!!o&&i(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visib [...]
+}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass( [...]
+}catch(n){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,n,a,r,h,l,u;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),n=e.datepicker._get(i,"beforeShow"),a=n?n.apply(t,[t,i]) [...]
+},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0 [...]
+}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button type='button'></button>" [...]
+f&&e.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=e.effects.setTransition(i,d,a.from.y,i.from),i.to=e.effects.setTransition(i,d,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=e.effects.setTransition(i,c,a.from.x,i.from),i.to=e.effects.setTransition(i,c,a.to.x,i.to)),i [...]
+return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.s [...]
+}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(i,s){var n,a,o,r=e(s).uniqueId().attr("id"),h=e(s).closest("li"),l=h.attr("aria-controls");t._isLocal(s)?(n=s.hash,o=n.substring(1),a=t.element.find(t._sanitizeSelector(n))):(o=h.attr("aria-controls")||e({}).uniqueId()[0].id,n="#"+o,a=t.element.find(n),a.length||(a=t._createPanel(o),a.insertAfter(t.panels[i-1]||t.tablist)),a.attr("aria-live","polite")),a.length&&(t.panels=t.pa [...]
+
+/* JQuery UJS 3.1.1 */
+(function(e,t){if(e.rails!==t){e.error("jquery-ujs has already been loaded!")}var n;var r=e(document);e.rails=n={linkClickSelector:"a[data-confirm], a[data-method], a[data-remote], a[data-disable-with], a[data-disable]",buttonClickSelector:"button[data-remote], button[data-confirm]",inputChangeSelector:"select[data-remote], input[data-remote], textarea[data-remote]",formSubmitSelector:"form",formInputClickSelector:"form input[type=submit], form input[type=image], form button[type=submit] [...]
diff --git a/public/javascripts/jquery-1.8.3-ui-1.9.2-ujs-2.0.3.js b/public/javascripts/jquery-1.8.3-ui-1.9.2-ujs-2.0.3.js
deleted file mode 100644
index 5fe1a15..0000000
--- a/public/javascripts/jquery-1.8.3-ui-1.9.2-ujs-2.0.3.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*! jQuery v1.8.3 jquery.com | jquery.org/license */
-(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){retur [...]
-
-/*! jQuery UI - v1.9.2 - 2012-12-26
-* http://jqueryui.com
-* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui [...]
-* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
-(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return; [...]
-
-/* JQuery UJS 2.0.3 */
-(function(a,b){var c=function(){var b=a(document).data("events");return b&&b.click&&a.grep(b.click,function(a){return a.namespace==="rails"}).length};if(c()){a.error("jquery-ujs has already been loaded!")}var d;a.rails=d={linkClickSelector:"a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]",inputChangeSelector:"select[data-remote], input[data-remote], textarea[data-remote]",formSubmitSelector:"form",formInputClickSelector:"form input[type=submit], form input[type=imag [...]
diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css
index e04b4b2..2c6b62c 100644
--- a/public/stylesheets/application.css
+++ b/public/stylesheets/application.css
@@ -254,6 +254,8 @@ table.boards td.last-message {text-align:left;font-size:80%;}
 
 table.messages td.last_message {text-align:left;}
 
+#query_form_content {font-size:90%;}
+
 table.query-columns {
   border-collapse: collapse;
   border: 0;
@@ -341,7 +343,7 @@ div.issue table.attributes td {width:28%;}
 #issue_tree td.checkbox, #relations td.checkbox {display:none;}
 #relations td.buttons {padding:0;}
 
-fieldset.collapsible { border-width: 1px 0 0 0; font-size: 0.9em; }
+fieldset.collapsible {border-width: 1px 0 0 0;}
 fieldset.collapsible>legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; }
 fieldset.collapsible.collapsed>legend { background-image: url(../images/arrow_collapsed.png); }
 
@@ -454,10 +456,12 @@ ul.properties li span {font-style:italic;}
 
 #workflow_copy_form select { width: 200px; }
 table.transitions td.enabled {background: #bfb;}
-table.fields_permissions select {font-size:90%}
+#workflow_form table select {font-size:90%; max-width:100px;}
 table.fields_permissions td.readonly {background:#ddd;}
 table.fields_permissions td.required {background:#d88;}
 
+select.expandable {vertical-align:top;}
+
 textarea#custom_field_possible_values {width: 95%; resize:vertical}
 textarea#custom_field_default_value {width: 95%; resize:vertical}
 
diff --git a/public/stylesheets/jquery/images/animated-overlay.gif b/public/stylesheets/jquery/images/animated-overlay.gif
new file mode 100644
index 0000000..d441f75
Binary files /dev/null and b/public/stylesheets/jquery/images/animated-overlay.gif differ
diff --git a/public/stylesheets/jquery/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/public/stylesheets/jquery/images/ui-bg_diagonals-thick_18_b81900_40x40.png
index 954e22d..b85f94c 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_diagonals-thick_18_b81900_40x40.png and b/public/stylesheets/jquery/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_diagonals-thick_20_666666_40x40.png b/public/stylesheets/jquery/images/ui-bg_diagonals-thick_20_666666_40x40.png
index 64ece57..c746c79 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_diagonals-thick_20_666666_40x40.png and b/public/stylesheets/jquery/images/ui-bg_diagonals-thick_20_666666_40x40.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_flat_10_000000_40x100.png b/public/stylesheets/jquery/images/ui-bg_flat_10_000000_40x100.png
index abdc010..328e444 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_flat_10_000000_40x100.png and b/public/stylesheets/jquery/images/ui-bg_flat_10_000000_40x100.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_glass_100_eef5fd_1x400.png b/public/stylesheets/jquery/images/ui-bg_glass_100_eef5fd_1x400.png
index c3492e3..a4cfcbe 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_glass_100_eef5fd_1x400.png and b/public/stylesheets/jquery/images/ui-bg_glass_100_eef5fd_1x400.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_glass_100_f6f6f6_1x400.png b/public/stylesheets/jquery/images/ui-bg_glass_100_f6f6f6_1x400.png
index 9b383f4..2029292 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_glass_100_f6f6f6_1x400.png and b/public/stylesheets/jquery/images/ui-bg_glass_100_f6f6f6_1x400.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_glass_65_ffffff_1x400.png b/public/stylesheets/jquery/images/ui-bg_glass_65_ffffff_1x400.png
index 42ccba2..0850cce 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_glass_65_ffffff_1x400.png and b/public/stylesheets/jquery/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_gloss-wave_35_759fcf_500x100.png b/public/stylesheets/jquery/images/ui-bg_gloss-wave_35_759fcf_500x100.png
index 70b39a8..df35d94 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_gloss-wave_35_759fcf_500x100.png and b/public/stylesheets/jquery/images/ui-bg_gloss-wave_35_759fcf_500x100.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/public/stylesheets/jquery/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
index f127367..05521f3 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_highlight-soft_100_eeeeee_1x100.png and b/public/stylesheets/jquery/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ
diff --git a/public/stylesheets/jquery/images/ui-bg_highlight-soft_75_759fcf_1x100.png b/public/stylesheets/jquery/images/ui-bg_highlight-soft_75_759fcf_1x100.png
index 3fc3f9b..3d7611b 100644
Binary files a/public/stylesheets/jquery/images/ui-bg_highlight-soft_75_759fcf_1x100.png and b/public/stylesheets/jquery/images/ui-bg_highlight-soft_75_759fcf_1x100.png differ
diff --git a/public/stylesheets/jquery/images/ui-icons_222222_256x240.png b/public/stylesheets/jquery/images/ui-icons_222222_256x240.png
index b273ff1..c1cb117 100644
Binary files a/public/stylesheets/jquery/images/ui-icons_222222_256x240.png and b/public/stylesheets/jquery/images/ui-icons_222222_256x240.png differ
diff --git a/public/stylesheets/jquery/images/ui-icons_759fcf_256x240.png b/public/stylesheets/jquery/images/ui-icons_759fcf_256x240.png
index e0c6374..9747215 100644
Binary files a/public/stylesheets/jquery/images/ui-icons_759fcf_256x240.png and b/public/stylesheets/jquery/images/ui-icons_759fcf_256x240.png differ
diff --git a/public/stylesheets/jquery/images/ui-icons_ffd27a_256x240.png b/public/stylesheets/jquery/images/ui-icons_ffd27a_256x240.png
index e117eff..8b6c058 100644
Binary files a/public/stylesheets/jquery/images/ui-icons_ffd27a_256x240.png and b/public/stylesheets/jquery/images/ui-icons_ffd27a_256x240.png differ
diff --git a/public/stylesheets/jquery/images/ui-icons_ffffff_256x240.png b/public/stylesheets/jquery/images/ui-icons_ffffff_256x240.png
index 42f8f99..4f624bb 100644
Binary files a/public/stylesheets/jquery/images/ui-icons_ffffff_256x240.png and b/public/stylesheets/jquery/images/ui-icons_ffffff_256x240.png differ
diff --git a/public/stylesheets/jquery/jquery-ui-1.11.0.css b/public/stylesheets/jquery/jquery-ui-1.11.0.css
new file mode 100644
index 0000000..f443fe9
--- /dev/null
+++ b/public/stylesheets/jquery/jquery-ui-1.11.0.css
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.11.0 - 2014-07-13
+* http://jqueryui.com
+* Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2C%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=759fcf&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=628db6&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDe [...]
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;heig [...]
diff --git a/public/stylesheets/jquery/jquery-ui-1.9.2.css b/public/stylesheets/jquery/jquery-ui-1.9.2.css
deleted file mode 100644
index 090d220..0000000
--- a/public/stylesheets/jquery/jquery-ui-1.9.2.css
+++ /dev/null
@@ -1,5 +0,0 @@
-/*! jQuery UI - v1.9.2 - 2012-12-26
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2C%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=759fcf&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=628db6&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_gla [...]
-* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-c [...]
diff --git a/script/about b/script/about
index cfec3b4..b830b97 100755
--- a/script/about
+++ b/script/about
@@ -1,6 +1,2 @@
 #!/usr/bin/env ruby
-
-ENV["RAILS_ENV"] ||= "production"
-require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
-puts
-puts Redmine::Info.environment
+abort "script/about no longer exists, please use bin/about instead."
diff --git a/script/rails b/script/rails
index f8da2cf..241275c 100755
--- a/script/rails
+++ b/script/rails
@@ -1,6 +1,2 @@
 #!/usr/bin/env ruby
-# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
-
-APP_PATH = File.expand_path('../../config/application',  __FILE__)
-require File.expand_path('../../config/boot',  __FILE__)
-require 'rails/commands'
+abort "script/rails no longer exists, please use bin/rails instead."
diff --git a/test/fixtures/mail_handler/gmail-iso8859-2.eml b/test/fixtures/mail_handler/gmail-iso8859-2.eml
new file mode 100644
index 0000000..f088050
--- /dev/null
+++ b/test/fixtures/mail_handler/gmail-iso8859-2.eml
@@ -0,0 +1,11 @@
+Date: Tue, 13 Aug 2013 10:56:04 +0700
+From: John Smith <JSmith at somenet.foo>
+Subject: =?ISO-8859-2?Q?Nikad_vi=B9e?=
+To: redmine at somenet.foo
+Content-Type: text/plain; charset=ISO-8859-2
+Content-Transfer-Encoding: quoted-printable
+
+Na =B9triku se su=B9i =B9osi=E6.
+
+--=20
+=B9osi=E6
diff --git a/test/fixtures/mail_handler/quoted_printable_utf8.eml b/test/fixtures/mail_handler/quoted_printable_utf8.eml
new file mode 100644
index 0000000..ae31ffc
--- /dev/null
+++ b/test/fixtures/mail_handler/quoted_printable_utf8.eml
@@ -0,0 +1,19 @@
+Date: Tue, 13 Aug 2013 10:56:04 +0700
+From: John Smith <JSmith at somenet.foo>
+Content-Type: multipart/alternative; boundary=001a11c260fa53f8dc04e3cc380b
+Subject: issue 14675
+To: redmine at somenet.foo
+
+--001a11c260fa53f8dc04e3cc380b
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: quoted-printable
+
+Freundliche Gr=C3=BCsse
+
+--001a11c260fa53f8dc04e3cc380b
+Content-Type: text/html; charset=UTF-8
+Content-Transfer-Encoding: quoted-printable
+
+<div dir=3D"ltr">Freundliche Gr=C3=BCsse<br></div>
+
+--001a11c260fa53f8dc04e3cc380b--
diff --git a/test/functional/account_controller_test.rb b/test/functional/account_controller_test.rb
index faf7356..114684b 100644
--- a/test/functional/account_controller_test.rb
+++ b/test/functional/account_controller_test.rb
@@ -72,8 +72,8 @@ class AccountControllerTest < ActionController::TestCase
   end
 
   def test_login_with_suburi_should_redirect_to_back_url_param
-    @relative_url_root = ApplicationController.relative_url_root
-    ApplicationController.relative_url_root = '/redmine'
+    @relative_url_root = Redmine::Utils.relative_url_root
+    Redmine::Utils.relative_url_root = '/redmine'
 
     back_urls = [
       'http://test.host/redmine/issues/show/1',
@@ -84,7 +84,7 @@ class AccountControllerTest < ActionController::TestCase
       assert_redirected_to back_url
     end
   ensure
-    ApplicationController.relative_url_root = @relative_url_root
+    Redmine::Utils.relative_url_root = @relative_url_root
   end
 
   def test_login_should_not_redirect_to_another_host
@@ -99,8 +99,8 @@ class AccountControllerTest < ActionController::TestCase
   end
 
   def test_login_with_suburi_should_not_redirect_to_another_suburi
-    @relative_url_root = ApplicationController.relative_url_root
-    ApplicationController.relative_url_root = '/redmine'
+    @relative_url_root = Redmine::Utils.relative_url_root
+    Redmine::Utils.relative_url_root = '/redmine'
 
     back_urls = [
       'http://test.host/',
@@ -115,7 +115,7 @@ class AccountControllerTest < ActionController::TestCase
       assert_redirected_to '/my/page'
     end
   ensure
-    ApplicationController.relative_url_root = @relative_url_root
+    Redmine::Utils.relative_url_root = @relative_url_root
   end
 
   def test_login_with_wrong_password
diff --git a/test/functional/activities_controller_test.rb b/test/functional/activities_controller_test.rb
index 49d5aff..06c1624 100644
--- a/test/functional/activities_controller_test.rb
+++ b/test/functional/activities_controller_test.rb
@@ -127,11 +127,13 @@ class ActivitiesControllerTest < ActionController::TestCase
   end
 
   def test_index_atom_feed_with_one_item_type
-    get :index, :format => 'atom', :show_issues => '1'
-    assert_response :success
-    assert_template 'common/feed'
-
-    assert_select 'title', :text => /Issues/
+    with_settings :default_language => 'en' do
+      get :index, :format => 'atom', :show_issues => '1'
+      assert_response :success
+      assert_template 'common/feed'
+  
+      assert_select 'title', :text => /Issues/
+    end
   end
 
   def test_index_should_show_private_notes_with_permission_only
diff --git a/test/functional/admin_controller_test.rb b/test/functional/admin_controller_test.rb
index 541f86a..a87c92b 100644
--- a/test/functional/admin_controller_test.rb
+++ b/test/functional/admin_controller_test.rb
@@ -103,11 +103,12 @@ class AdminControllerTest < ActionController::TestCase
   end
 
   def test_no_plugins
-    Redmine::Plugin.clear
+    Redmine::Plugin.stubs(:registered_plugins).returns({})
 
     get :plugins
     assert_response :success
     assert_template 'plugins'
+    assert_equal [], assigns(:plugins)
   end
 
   def test_plugins
diff --git a/test/functional/attachments_controller_test.rb b/test/functional/attachments_controller_test.rb
index 5800307..3ab332f 100644
--- a/test/functional/attachments_controller_test.rb
+++ b/test/functional/attachments_controller_test.rb
@@ -139,8 +139,7 @@ class AttachmentsControllerTest < ActionController::TestCase
     assert a.save
     assert_equal 'japanese-utf-8.txt', a.filename
 
-    str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
-    str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
+    str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
 
     get :show, :id => a.id
     assert_response :success
@@ -193,12 +192,12 @@ class AttachmentsControllerTest < ActionController::TestCase
   end
 
   def test_show_text_file_should_send_if_too_big
-    Setting.file_max_size_displayed = 512
-    Attachment.find(4).update_attribute :filesize, 754.kilobyte
-
-    get :show, :id => 4
-    assert_response :success
-    assert_equal 'application/x-ruby', @response.content_type
+    with_settings :file_max_size_displayed => 512 do
+      Attachment.find(4).update_attribute :filesize, 754.kilobyte
+      get :show, :id => 4
+      assert_response :success
+      assert_equal 'application/x-ruby', @response.content_type
+    end
     set_tmp_attachments_directory
   end
 
@@ -250,6 +249,13 @@ class AttachmentsControllerTest < ActionController::TestCase
     get :download, :id => 4
     assert_response :success
     assert_equal 'application/x-ruby', @response.content_type
+    etag = @response.etag
+    assert_not_nil etag
+
+    @request.env["HTTP_IF_NONE_MATCH"] = etag
+    get :download, :id => 4
+    assert_response 304
+
     set_tmp_attachments_directory
   end
 
@@ -284,10 +290,16 @@ class AttachmentsControllerTest < ActionController::TestCase
     def test_thumbnail
       Attachment.clear_thumbnails
       @request.session[:user_id] = 2
-
       get :thumbnail, :id => 16
       assert_response :success
       assert_equal 'image/png', response.content_type
+
+      etag = @response.etag
+      assert_not_nil etag
+
+      @request.env["HTTP_IF_NONE_MATCH"] = etag
+      get :thumbnail, :id => 16
+      assert_response 304
     end
 
     def test_thumbnail_should_not_exceed_maximum_size
diff --git a/test/functional/calendars_controller_test.rb b/test/functional/calendars_controller_test.rb
index e67d05d..01f9a8c 100644
--- a/test/functional/calendars_controller_test.rb
+++ b/test/functional/calendars_controller_test.rb
@@ -48,10 +48,10 @@ class CalendarsControllerTest < ActionController::TestCase
   end
 
   def test_week_number_calculation
-    Setting.start_of_week = 7
-
-    get :show, :month => '1', :year => '2010'
-    assert_response :success
+    with_settings :start_of_week => 7 do
+      get :show, :month => '1', :year => '2010'
+      assert_response :success
+    end
 
     assert_select 'tr' do
       assert_select 'td.week-number', :text => '53'
@@ -65,9 +65,10 @@ class CalendarsControllerTest < ActionController::TestCase
       assert_select 'td.even', :text => '9'
     end
 
-    Setting.start_of_week = 1
-    get :show, :month => '1', :year => '2010'
-    assert_response :success
+    with_settings :start_of_week => 1 do
+      get :show, :month => '1', :year => '2010'
+      assert_response :success
+    end
 
     assert_select 'tr' do
       assert_select 'td.week-number', :text => '53'
diff --git a/test/functional/context_menus_controller_test.rb b/test/functional/context_menus_controller_test.rb
index b83c2d6..317696f 100644
--- a/test/functional/context_menus_controller_test.rb
+++ b/test/functional/context_menus_controller_test.rb
@@ -56,12 +56,14 @@ class ContextMenusControllerTest < ActionController::TestCase
   end
 
   def test_context_menu_one_issue_by_anonymous
-    get :issues, :ids => [1]
-    assert_response :success
-    assert_template 'context_menus/issues'
-    assert_tag :tag => 'a', :content => 'Delete',
-                            :attributes => { :href => '#',
-                                             :class => 'icon-del disabled' }
+    with_settings :default_language => 'en' do
+      get :issues, :ids => [1]
+      assert_response :success
+      assert_template 'context_menus/issues'
+      assert_tag :tag => 'a', :content => 'Delete',
+                              :attributes => { :href => '#',
+                                               :class => 'icon-del disabled' }
+    end
   end
 
   def test_context_menu_multiple_issues_of_same_project
diff --git a/test/functional/custom_fields_controller_test.rb b/test/functional/custom_fields_controller_test.rb
index 76579d7..0d86df2 100644
--- a/test/functional/custom_fields_controller_test.rb
+++ b/test/functional/custom_fields_controller_test.rb
@@ -112,7 +112,7 @@ class CustomFieldsControllerTest < ActionController::TestCase
   end
 
   def test_new_js
-    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}, :format => 'js'
+    xhr :get, :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}, :format => 'js'
     assert_response :success
     assert_template 'new'
     assert_equal 'text/javascript', response.content_type
diff --git a/test/functional/groups_controller_test.rb b/test/functional/groups_controller_test.rb
index 35f0a43..d1a2b67 100644
--- a/test/functional/groups_controller_test.rb
+++ b/test/functional/groups_controller_test.rb
@@ -30,6 +30,12 @@ class GroupsControllerTest < ActionController::TestCase
     assert_template 'index'
   end
 
+  def test_index_should_show_user_count
+    get :index
+    assert_response :success
+    assert_select 'tr#group-11 td.user_count', :text => '1'
+  end
+
   def test_show
     get :show, :id => 10
     assert_response :success
@@ -195,7 +201,7 @@ class GroupsControllerTest < ActionController::TestCase
   end
 
   def test_autocomplete_for_user
-    get :autocomplete_for_user, :id => 10, :q => 'smi', :format => 'js'
+    xhr :get, :autocomplete_for_user, :id => 10, :q => 'smi', :format => 'js'
     assert_response :success
     assert_include 'John Smith', response.body
   end
diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb
index 9f3542e..5d78b6a 100644
--- a/test/functional/issues_controller_test.rb
+++ b/test/functional/issues_controller_test.rb
@@ -473,12 +473,8 @@ class IssuesControllerTest < ActionController::TestCase
 
   def test_index_csv_big_5
     with_settings :default_language => "zh-TW" do
-      str_utf8  = "\xe4\xb8\x80\xe6\x9c\x88"
-      str_big5  = "\xa4@\xa4\xeb"
-      if str_utf8.respond_to?(:force_encoding)
-        str_utf8.force_encoding('UTF-8')
-        str_big5.force_encoding('Big5')
-      end
+      str_utf8  = "\xe4\xb8\x80\xe6\x9c\x88".force_encoding('UTF-8')
+      str_big5  = "\xa4@\xa4\xeb".force_encoding('Big5')
       issue = Issue.generate!(:subject => str_utf8)
 
       get :index, :project_id => 1, 
@@ -487,10 +483,7 @@ class IssuesControllerTest < ActionController::TestCase
                   :format => 'csv'
       assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")
-      s1 = "\xaa\xac\xbaA"
-      if str_utf8.respond_to?(:force_encoding)
-        s1.force_encoding('Big5')
-      end
+      s1 = "\xaa\xac\xbaA".force_encoding('Big5')
       assert_include s1, lines[0]
       assert_include str_big5, lines[1]
     end
@@ -498,10 +491,7 @@ class IssuesControllerTest < ActionController::TestCase
 
   def test_index_csv_cannot_convert_should_be_replaced_big_5
     with_settings :default_language => "zh-TW" do
-      str_utf8  = "\xe4\xbb\xa5\xe5\x86\x85"
-      if str_utf8.respond_to?(:force_encoding)
-        str_utf8.force_encoding('UTF-8')
-      end
+      str_utf8  = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8')
       issue = Issue.generate!(:subject => str_utf8)
 
       get :index, :project_id => 1, 
@@ -512,20 +502,14 @@ class IssuesControllerTest < ActionController::TestCase
                   :set_filter => 1
       assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")
-      s1 = "\xaa\xac\xbaA" # status
-      if str_utf8.respond_to?(:force_encoding)
-        s1.force_encoding('Big5')
-      end
+      s1 = "\xaa\xac\xbaA".force_encoding('Big5') # status
       assert lines[0].include?(s1)
       s2 = lines[1].split(",")[2]
-      if s1.respond_to?(:force_encoding)
-        s3 = "\xa5H?" # subject
-        s3.force_encoding('Big5')
-        assert_equal s3, s2
-      elsif RUBY_PLATFORM == 'java'
+      if RUBY_PLATFORM == 'java'
         assert_equal "??", s2
       else
-        assert_equal "\xa5H???", s2
+        s3 = "\xa5H?".force_encoding('Big5') # subject
+        assert_equal s3, s2
       end
     end
   end
@@ -3107,20 +3091,15 @@ class IssuesControllerTest < ActionController::TestCase
   def test_put_update_with_attachment_that_fails_to_save
     set_tmp_attachments_directory
 
-    # Delete all fixtured journals, a race condition can occur causing the wrong
-    # journal to get fetched in the next find.
-    Journal.delete_all
-
-    # Mock out the unsaved attachment
-    Attachment.any_instance.stubs(:create).returns(Attachment.new)
-
     # anonymous user
-    put :update,
-         :id => 1,
-         :issue => {:notes => ''},
-         :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
-    assert_redirected_to :action => 'show', :id => '1'
-    assert_equal '1 file(s) could not be saved.', flash[:warning]
+    with_settings :attachment_max_size => 0 do
+      put :update,
+           :id => 1,
+           :issue => {:notes => ''},
+           :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
+      assert_redirected_to :action => 'show', :id => '1'
+      assert_equal '1 file(s) could not be saved.', flash[:warning]
+    end
   end
 
   def test_put_update_with_no_change
@@ -3366,7 +3345,7 @@ class IssuesControllerTest < ActionController::TestCase
     post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
     assert_response :success
     assert_template 'bulk_edit'
-    assert_equal Project.find(1).shared_versions.open.all.sort, assigns(:versions).sort
+    assert_equal Project.find(1).shared_versions.open.to_a.sort, assigns(:versions).sort
 
     assert_select 'select[name=?]', 'issue[fixed_version_id]' do
       assert_select 'option', :text => '2.0'
diff --git a/test/functional/issues_custom_fields_visibility_test.rb b/test/functional/issues_custom_fields_visibility_test.rb
index cf16466..afa54c9 100644
--- a/test/functional/issues_custom_fields_visibility_test.rb
+++ b/test/functional/issues_custom_fields_visibility_test.rb
@@ -199,8 +199,8 @@ class IssuesCustomFieldsVisibilityTest < ActionController::TestCase
     p1 = Project.generate!
     p2 = Project.generate!
     user = User.generate!
-    User.add_to_project(user, p1, Role.where(:id => [1, 3]).all)
-    User.add_to_project(user, p2, Role.where(:id => 3).all)
+    User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a)
+    User.add_to_project(user, p2, Role.where(:id => 3).to_a)
     Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'})
     Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'})
     Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'})
diff --git a/test/functional/members_controller_test.rb b/test/functional/members_controller_test.rb
index 4710916..a1ab6f9 100644
--- a/test/functional/members_controller_test.rb
+++ b/test/functional/members_controller_test.rb
@@ -104,7 +104,7 @@ class MembersControllerTest < ActionController::TestCase
   end
 
   def test_autocomplete
-    get :autocomplete, :project_id => 1, :q => 'mis', :format => 'js'
+    xhr :get, :autocomplete, :project_id => 1, :q => 'mis', :format => 'js'
     assert_response :success
     assert_include 'User Misc', response.body
   end
diff --git a/test/functional/messages_controller_test.rb b/test/functional/messages_controller_test.rb
index 075bab9..8b15d51 100644
--- a/test/functional/messages_controller_test.rb
+++ b/test/functional/messages_controller_test.rb
@@ -59,8 +59,8 @@ class MessagesControllerTest < ActionController::TestCase
     assert_template 'show'
     replies = assigns(:replies)
     assert_not_nil replies
-    assert !replies.include?(message.children.order('id').first)
-    assert replies.include?(message.children.order('id').last)
+    assert_not_include message.children.reorder('id').first, replies
+    assert_include message.children.reorder('id').last, replies
   end
 
   def test_show_with_reply_permission
diff --git a/test/functional/my_controller_test.rb b/test/functional/my_controller_test.rb
index 6577aee..3280de8 100644
--- a/test/functional/my_controller_test.rb
+++ b/test/functional/my_controller_test.rb
@@ -167,7 +167,7 @@ class MyControllerTest < ActionController::TestCase
                     :new_password_confirmation => 'secret1234'
     assert_response :success
     assert_template 'password'
-    assert_error_tag :content => /Password doesn&#x27;t match confirmation/
+    assert_error_tag :content => /Password doesn.*t match confirmation/
 
     # wrong password
     post :password, :password => 'wrongpassword',
diff --git a/test/functional/repositories_bazaar_controller_test.rb b/test/functional/repositories_bazaar_controller_test.rb
index 2321f2e..5da8549 100644
--- a/test/functional/repositories_bazaar_controller_test.rb
+++ b/test/functional/repositories_bazaar_controller_test.rb
@@ -26,7 +26,7 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase
   REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
   REPOSITORY_PATH_TRUNK = File.join(REPOSITORY_PATH, "trunk")
   PRJ_ID = 3
-  CHAR_1_UTF8_HEX   = "\xc3\x9c"
+  CHAR_1_UTF8_HEX   = "\xc3\x9c".dup.force_encoding('UTF-8')
 
   def setup
     User.current = nil
@@ -36,10 +36,6 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase
                     :url          => REPOSITORY_PATH_TRUNK,
                     :log_encoding => 'UTF-8')
     assert @repository
-    @char_1_utf8 = CHAR_1_UTF8_HEX.dup
-    if @char_1_utf8.respond_to?(:force_encoding)
-      @char_1_utf8.force_encoding('UTF-8')
-    end
   end
 
   if File.directory?(REPOSITORY_PATH)
@@ -176,31 +172,29 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase
       end
     end
 
-    if REPOSITORY_PATH.respond_to?(:force_encoding)
-      def test_annotate_author_non_ascii
-        log_encoding = nil
-        if Encoding.locale_charmap == "UTF-8" ||
-             Encoding.locale_charmap == "ISO-8859-1"
-          log_encoding = Encoding.locale_charmap
-        end
-        unless log_encoding.nil?
-          repository = Repository::Bazaar.create(
-                        :project      => @project,
-                        :url          => File.join(REPOSITORY_PATH, "author_non_ascii"),
-                        :identifier => 'author_non_ascii',
-                        :log_encoding => log_encoding)
-          assert repository
-          get :annotate, :id => PRJ_ID, :repository_id => 'author_non_ascii',
-              :path => repository_path_hash(['author-non-ascii-test.txt'])[:param]
-          assert_response :success
-          assert_template 'annotate'
-          assert_select "th.line-num", :text => '1' do
-            assert_select "+ td.revision" do
-              assert_select "a", :text => '2'
-              assert_select "+ td.author", :text => "test #{@char_1_utf8}" do
-                assert_select "+ td",
-                              :text => "author non ASCII test"
-              end
+    def test_annotate_author_non_ascii
+      log_encoding = nil
+      if Encoding.locale_charmap == "UTF-8" ||
+           Encoding.locale_charmap == "ISO-8859-1"
+        log_encoding = Encoding.locale_charmap
+      end
+      unless log_encoding.nil?
+        repository = Repository::Bazaar.create(
+                      :project      => @project,
+                      :url          => File.join(REPOSITORY_PATH, "author_non_ascii"),
+                      :identifier => 'author_non_ascii',
+                      :log_encoding => log_encoding)
+        assert repository
+        get :annotate, :id => PRJ_ID, :repository_id => 'author_non_ascii',
+            :path => repository_path_hash(['author-non-ascii-test.txt'])[:param]
+        assert_response :success
+        assert_template 'annotate'
+        assert_select "th.line-num", :text => '1' do
+          assert_select "+ td.revision" do
+            assert_select "a", :text => '2'
+            assert_select "+ td.author", :text => "test #{CHAR_1_UTF8_HEX}" do
+              assert_select "+ td",
+                            :text => "author non ASCII test"
             end
           end
         end
diff --git a/test/functional/repositories_cvs_controller_test.rb b/test/functional/repositories_cvs_controller_test.rb
index d16ca4f..5e245bc 100644
--- a/test/functional/repositories_cvs_controller_test.rb
+++ b/test/functional/repositories_cvs_controller_test.rb
@@ -200,7 +200,7 @@ class RepositoriesCvsControllerTest < ActionController::TestCase
         assert_tag :tag => 'th', :attributes => { :class => 'filename' },
                                  :content => /test\/README/
         assert_tag :tag => 'th', :attributes => { :class => 'filename' },
-                                 :content => /test\/images\/delete.png	/
+                                 :content => /test\/images\/delete.png/
         assert_tag :tag => 'th', :attributes => { :class => 'filename' },
                                  :content => /test\/images\/edit.png/
         assert_tag :tag => 'th', :attributes => { :class => 'filename' },
diff --git a/test/functional/repositories_filesystem_controller_test.rb b/test/functional/repositories_filesystem_controller_test.rb
index 0a1f7da..ee904d8 100644
--- a/test/functional/repositories_filesystem_controller_test.rb
+++ b/test/functional/repositories_filesystem_controller_test.rb
@@ -27,8 +27,7 @@ class RepositoriesFilesystemControllerTest < ActionController::TestCase
   PRJ_ID = 3
 
   def setup
-    @ruby19_non_utf8_pass =
-        (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
+    @ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8'
     User.current = nil
     Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
     @project = Project.find(PRJ_ID)
@@ -94,12 +93,11 @@ class RepositoriesFilesystemControllerTest < ActionController::TestCase
                    :attributes => { :class => 'line-num' },
                    :sibling => { :tag => 'td', :content => /japanese/ }
         if @ruby19_non_utf8_pass
-          puts "TODO: show repository file contents test fails in Ruby 1.9 " +
-               "and Encoding.default_external is not UTF-8. " +
+          puts "TODO: show repository file contents test fails " +
+               "when Encoding.default_external is not UTF-8. " +
                "Current value is '#{Encoding.default_external.to_s}'"
         else
-          str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
-          str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
+          str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
           assert_tag :tag => 'th',
                      :content => '3',
                      :attributes => { :class => 'line-num' },
@@ -109,7 +107,7 @@ class RepositoriesFilesystemControllerTest < ActionController::TestCase
     end
 
     def test_show_utf16
-      enc = (RUBY_VERSION == "1.9.2" ? 'UTF-16LE' : 'UTF-16')
+      enc = 'UTF-16'
       with_settings :repositories_encodings => enc do
         get :entry, :id => PRJ_ID,
             :path => repository_path_hash(['japanese', 'utf-16.txt'])[:param]
diff --git a/test/functional/repositories_git_controller_test.rb b/test/functional/repositories_git_controller_test.rb
index 33bba8c..e20adea 100644
--- a/test/functional/repositories_git_controller_test.rb
+++ b/test/functional/repositories_git_controller_test.rb
@@ -26,8 +26,8 @@ class RepositoriesGitControllerTest < ActionController::TestCase
   REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
   REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
   PRJ_ID     = 3
-  CHAR_1_HEX = "\xc3\x9c"
-  FELIX_HEX  = "Felix Sch\xC3\xA4fer"
+  CHAR_1_HEX = "\xc3\x9c".force_encoding('UTF-8')
+  FELIX_HEX  = "Felix Sch\xC3\xA4fer".force_encoding('UTF-8')
   NUM_REV = 28
 
   ## Git, Mercurial and CVS path encodings are binary.
@@ -39,8 +39,7 @@ class RepositoriesGitControllerTest < ActionController::TestCase
   JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
 
   def setup
-    @ruby19_non_utf8_pass =
-      (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
+    @ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8'
 
     User.current = nil
     @project    = Project.find(PRJ_ID)
@@ -50,12 +49,6 @@ class RepositoriesGitControllerTest < ActionController::TestCase
                       :path_encoding => 'ISO-8859-1'
                       )
     assert @repository
-    @char_1        = CHAR_1_HEX.dup
-    @felix_utf8  = FELIX_HEX.dup
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-      @felix_utf8.force_encoding('UTF-8')
-    end
   end
 
   def test_create_and_update
@@ -231,7 +224,7 @@ class RepositoriesGitControllerTest < ActionController::TestCase
         with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
           ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
             get :entry, :id => PRJ_ID,
-                :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
+                :path => repository_path_hash(['latin-1-dir', "test-#{CHAR_1_HEX}.txt"])[:param],
                 :rev => r1
             assert_response :success
             assert_template 'entry'
@@ -239,7 +232,7 @@ class RepositoriesGitControllerTest < ActionController::TestCase
                    :content => '1',
                    :attributes => { :class => 'line-num' },
                    :sibling => { :tag => 'td',
-                                 :content => /test-#{@char_1}.txt/ }
+                                 :content => /test-#{CHAR_1_HEX}.txt/ }
           end
         end
       end
@@ -377,7 +370,7 @@ class RepositoriesGitControllerTest < ActionController::TestCase
                       :url           => REPOSITORY_PATH,
                       :identifier => 'test-diff-path',
                       :path_encoding => 'ISO-8859-1'
-                      );
+                      )
       assert repo
       assert_equal false, repo.is_default
       assert_equal 'test-diff-path', repo.identifier
@@ -419,14 +412,14 @@ class RepositoriesGitControllerTest < ActionController::TestCase
                          :descendant => {
                            :tag => 'th',
                            :attributes => { :class => 'filename' } ,
-                           :content => /latin-1-dir\/test-#{@char_1}.txt/ ,
+                           :content => /latin-1-dir\/test-#{CHAR_1_HEX}.txt/ ,
                           },
                          :sibling => {
                            :tag => 'tbody',
                            :descendant => {
                               :tag => 'td',
                               :attributes => { :class => /diff_in/ },
-                              :content => /test-#{@char_1}.txt/
+                              :content => /test-#{CHAR_1_HEX}.txt/
                            }
                          }
             end
@@ -498,11 +491,13 @@ class RepositoriesGitControllerTest < ActionController::TestCase
     end
 
     def test_annotate_binary_file
-      get :annotate, :id => PRJ_ID,
-          :path => repository_path_hash(['images', 'edit.png'])[:param]
-      assert_response 500
-      assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
-                              :content => /cannot be annotated/
+      with_settings :default_language => 'en' do
+        get :annotate, :id => PRJ_ID,
+            :path => repository_path_hash(['images', 'edit.png'])[:param]
+        assert_response 500
+        assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
+                                :content => /cannot be annotated/
+      end
     end
 
     def test_annotate_error_when_too_big
@@ -533,14 +528,14 @@ class RepositoriesGitControllerTest < ActionController::TestCase
         with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
           ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
             get :annotate, :id => PRJ_ID,
-                :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
+                :path => repository_path_hash(['latin-1-dir', "test-#{CHAR_1_HEX}.txt"])[:param],
                 :rev => r1
             assert_select "th.line-num", :text => '1' do
               assert_select "+ td.revision" do
                 assert_select "a", :text => '57ca437c'
                 assert_select "+ td.author", :text => "jsmith" do
                   assert_select "+ td",
-                                :text => "test-#{@char_1}.txt"
+                                :text => "test-#{CHAR_1_HEX}.txt"
                 end
               end
             end
@@ -557,7 +552,7 @@ class RepositoriesGitControllerTest < ActionController::TestCase
         assert_select "th.line-num", :text => '1' do
           assert_select "+ td.revision" do
             assert_select "a", :text => '83ca5fd5'
-            assert_select "+ td.author", :text => @felix_utf8 do
+            assert_select "+ td.author", :text => FELIX_HEX do
               assert_select "+ td",
                             :text => "And this is a file with a leading and trailing space..."
             end
@@ -643,8 +638,8 @@ class RepositoriesGitControllerTest < ActionController::TestCase
     private
 
     def puts_ruby19_non_utf8_pass
-      puts "TODO: This test fails in Ruby 1.9 " +
-           "and Encoding.default_external is not UTF-8. " +
+      puts "TODO: This test fails " +
+           "when Encoding.default_external is not UTF-8. " +
            "Current value is '#{Encoding.default_external.to_s}'"
     end
   else
diff --git a/test/functional/repositories_mercurial_controller_test.rb b/test/functional/repositories_mercurial_controller_test.rb
index 8eec4f3..382aa5c 100644
--- a/test/functional/repositories_mercurial_controller_test.rb
+++ b/test/functional/repositories_mercurial_controller_test.rb
@@ -28,8 +28,7 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase
   PRJ_ID     = 3
   NUM_REV    = 34
 
-  ruby19_non_utf8_pass =
-     (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
+  ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8'
 
   def setup
     User.current = nil
@@ -41,21 +40,15 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase
                       )
     assert @repository
     @diff_c_support = true
-    @char_1        = CHAR_1_HEX.dup
-    @tag_char_1    = "tag-#{CHAR_1_HEX}-00"
-    @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
-    @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-      @tag_char_1.force_encoding('UTF-8')
-      @branch_char_0.force_encoding('UTF-8')
-      @branch_char_1.force_encoding('UTF-8')
-    end
+    @char_1        = CHAR_1_HEX.dup.force_encoding('UTF-8')
+    @tag_char_1    = "tag-#{CHAR_1_HEX}-00".force_encoding('UTF-8')
+    @branch_char_0 = "branch-#{CHAR_1_HEX}-00".force_encoding('UTF-8')
+    @branch_char_1 = "branch-#{CHAR_1_HEX}-01".force_encoding('UTF-8')
   end
 
   if ruby19_non_utf8_pass
-    puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
-         "and Encoding.default_external is not UTF-8. " +
+    puts "TODO: Mercurial functional test fails " +
+         "when Encoding.default_external is not UTF-8. " +
          "Current value is '#{Encoding.default_external.to_s}'"
     def test_fake; assert true end
   elsif File.directory?(REPOSITORY_PATH)
diff --git a/test/functional/roles_controller_test.rb b/test/functional/roles_controller_test.rb
index 54509b7..6e1fc3d 100644
--- a/test/functional/roles_controller_test.rb
+++ b/test/functional/roles_controller_test.rb
@@ -31,7 +31,7 @@ class RolesControllerTest < ActionController::TestCase
     assert_template 'index'
 
     assert_not_nil assigns(:roles)
-    assert_equal Role.order('builtin, position').all, assigns(:roles)
+    assert_equal Role.order('builtin, position').to_a, assigns(:roles)
 
     assert_tag :tag => 'a', :attributes => { :href => '/roles/1/edit' },
                             :content => 'Manager'
@@ -160,7 +160,7 @@ class RolesControllerTest < ActionController::TestCase
     assert_template 'permissions'
 
     assert_not_nil assigns(:roles)
-    assert_equal Role.order('builtin, position').all, assigns(:roles)
+    assert_equal Role.order('builtin, position').to_a, assigns(:roles)
 
     assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
                                                  :name => 'permissions[3][]',
diff --git a/test/functional/search_controller_test.rb b/test/functional/search_controller_test.rb
index 3c7f4e4..5b8e1ac 100644
--- a/test/functional/search_controller_test.rb
+++ b/test/functional/search_controller_test.rb
@@ -21,6 +21,7 @@ class SearchControllerTest < ActionController::TestCase
   fixtures :projects, :enabled_modules, :roles, :users, :members, :member_roles,
            :issues, :trackers, :issue_statuses, :enumerations,
            :custom_fields, :custom_values,
+           :custom_fields_projects, :custom_fields_trackers,
            :repositories, :changesets
 
   def setup
@@ -39,7 +40,9 @@ class SearchControllerTest < ActionController::TestCase
   end
 
   def test_search_all_projects
-    get :index, :q => 'recipe subproject commit', :all_words => ''
+    with_settings :default_language => 'en' do
+      get :index, :q => 'recipe subproject commit', :all_words => ''
+    end
     assert_response :success
     assert_template 'index'
 
diff --git a/test/functional/settings_controller_test.rb b/test/functional/settings_controller_test.rb
index fc64f87..6806fd2 100644
--- a/test/functional/settings_controller_test.rb
+++ b/test/functional/settings_controller_test.rb
@@ -18,7 +18,8 @@
 require File.expand_path('../../test_helper', __FILE__)
 
 class SettingsControllerTest < ActionController::TestCase
-  fixtures :users
+  fixtures :projects, :trackers, :issue_statuses, :issues,
+           :users
 
   def setup
     User.current = nil
@@ -148,7 +149,8 @@ class SettingsControllerTest < ActionController::TestCase
     assert_tag 'form', :attributes => {:action => '/settings/plugin/foo'},
       :descendant => {:tag => 'input', :attributes => {:name => 'settings[sample_setting]', :value => 'Plugin setting value'}}
 
-    Redmine::Plugin.clear
+  ensure
+    Redmine::Plugin.unregister(:foo)
   end
 
   def test_get_invalid_plugin_settings
@@ -162,7 +164,8 @@ class SettingsControllerTest < ActionController::TestCase
     get :plugin, :id => 'foo'
     assert_response 404
 
-    Redmine::Plugin.clear
+  ensure
+    Redmine::Plugin.unregister(:foo)
   end
 
   def test_post_plugin_settings
@@ -181,6 +184,7 @@ class SettingsControllerTest < ActionController::TestCase
     post :plugin, :id => 'foo', :settings => {'sample_setting' => 'Value'}
     assert_response 404
 
-    Redmine::Plugin.clear
+  ensure
+    Redmine::Plugin.unregister(:foo)
   end
 end
diff --git a/test/functional/time_entry_reports_controller_test.rb b/test/functional/time_entry_reports_controller_test.rb
index 56e23f9..161d31d 100644
--- a/test/functional/time_entry_reports_controller_test.rb
+++ b/test/functional/time_entry_reports_controller_test.rb
@@ -240,12 +240,8 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
 
   def test_csv_big_5
     Setting.default_language = "zh-TW"
-    str_utf8  = "\xe4\xb8\x80\xe6\x9c\x88"
-    str_big5  = "\xa4@\xa4\xeb"
-    if str_utf8.respond_to?(:force_encoding)
-      str_utf8.force_encoding('UTF-8')
-      str_big5.force_encoding('Big5')
-    end
+    str_utf8  = "\xe4\xb8\x80\xe6\x9c\x88".force_encoding('UTF-8')
+    str_big5  = "\xa4@\xa4\xeb".force_encoding('Big5')
     user = User.find_by_id(3)
     user.firstname = str_utf8
     user.lastname  = "test-lastname"
@@ -270,21 +266,14 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
     assert_equal 'text/csv; header=present', @response.content_type
     lines = @response.body.chomp.split("\n")    
     # Headers
-    s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
-    s2 = "\xa4u\xae\xc9\xc1`\xadp"
-    if s1.respond_to?(:force_encoding)
-      s1.force_encoding('Big5')
-      s2.force_encoding('Big5')
-    end
+    s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5')
+    s2 = "\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5')
     assert_equal s1, lines.first
     # Total row
     assert_equal "#{str_big5} #{user.lastname},7.30,7.30", lines[1]
     assert_equal "#{s2},7.30,7.30", lines[2]
 
-    str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
-    if str_tw.respond_to?(:force_encoding)
-      str_tw.force_encoding('UTF-8')
-    end
+    str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)".force_encoding('UTF-8')
     assert_equal str_tw, l(:general_lang_name)
     assert_equal 'Big5', l(:general_csv_encoding)
     assert_equal ',', l(:general_csv_separator)
@@ -293,10 +282,7 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
 
   def test_csv_cannot_convert_should_be_replaced_big_5
     Setting.default_language = "zh-TW"
-    str_utf8  = "\xe4\xbb\xa5\xe5\x86\x85"
-    if str_utf8.respond_to?(:force_encoding)
-      str_utf8.force_encoding('UTF-8')
-    end
+    str_utf8  = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8')
     user = User.find_by_id(3)
     user.firstname = str_utf8
     user.lastname  = "test-lastname"
@@ -321,20 +307,14 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
     assert_equal 'text/csv; header=present', @response.content_type
     lines = @response.body.chomp.split("\n")    
     # Headers
-    s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
-    if s1.respond_to?(:force_encoding)
-      s1.force_encoding('Big5')
-    end
+    s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5')
     assert_equal s1, lines.first
     # Total row
     s2 = ""
-    if s2.respond_to?(:force_encoding)
-      s2 = "\xa5H?"
-      s2.force_encoding('Big5')
-    elsif RUBY_PLATFORM == 'java'
+    if RUBY_PLATFORM == 'java'
       s2 = "??"
     else
-      s2 = "\xa5H???"
+      s2 = "\xa5H?".force_encoding('Big5')
     end
     assert_equal "#{s2} #{user.lastname},7.30,7.30", lines[1]
   end
@@ -362,21 +342,14 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
       assert_equal 'text/csv; header=present', @response.content_type
       lines = @response.body.chomp.split("\n")    
       # Headers
-      s1 = "Utilisateur;2011-11-11;Temps total"
-      s2 = "Temps total"
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding('ISO-8859-1')
-        s2.force_encoding('ISO-8859-1')
-      end
+      s1 = "Utilisateur;2011-11-11;Temps total".force_encoding('ISO-8859-1')
+      s2 = "Temps total".force_encoding('ISO-8859-1')
       assert_equal s1, lines.first
       # Total row
       assert_equal "#{user.firstname} #{user.lastname};7,30;7,30", lines[1]
       assert_equal "#{s2};7,30;7,30", lines[2]
 
-      str_fr = "Fran\xc3\xa7ais"
-      if str_fr.respond_to?(:force_encoding)
-        str_fr.force_encoding('UTF-8')
-      end
+      str_fr = "Fran\xc3\xa7ais".force_encoding('UTF-8')
       assert_equal str_fr, l(:general_lang_name)
       assert_equal 'ISO-8859-1', l(:general_csv_encoding)
       assert_equal ';', l(:general_csv_separator)
diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb
index a647750..9af5b41 100644
--- a/test/functional/timelog_controller_test.rb
+++ b/test/functional/timelog_controller_test.rb
@@ -670,16 +670,18 @@ class TimelogControllerTest < ActionController::TestCase
   end
 
   def test_index_csv_all_projects
-    Setting.date_format = '%m/%d/%Y'
-    get :index, :format => 'csv'
-    assert_response :success
-    assert_equal 'text/csv; header=present', response.content_type
+    with_settings :date_format => '%m/%d/%Y' do
+      get :index, :format => 'csv'
+      assert_response :success
+      assert_equal 'text/csv; header=present', response.content_type
+    end
   end
 
   def test_index_csv
-    Setting.date_format = '%m/%d/%Y'
-    get :index, :project_id => 1, :format => 'csv'
-    assert_response :success
-    assert_equal 'text/csv; header=present', response.content_type
+    with_settings :date_format => '%m/%d/%Y' do
+      get :index, :project_id => 1, :format => 'csv'
+      assert_response :success
+      assert_equal 'text/csv; header=present', response.content_type
+    end
   end
 end
diff --git a/test/functional/timelog_custom_fields_visibility_test.rb b/test/functional/timelog_custom_fields_visibility_test.rb
index 8f474c1..a5648de 100644
--- a/test/functional/timelog_custom_fields_visibility_test.rb
+++ b/test/functional/timelog_custom_fields_visibility_test.rb
@@ -95,8 +95,8 @@ class TimelogCustomFieldsVisibilityTest < ActionController::TestCase
     p1 = Project.generate!
     p2 = Project.generate!
     user = User.generate!
-    User.add_to_project(user, p1, Role.where(:id => [1, 3]).all)
-    User.add_to_project(user, p2, Role.where(:id => 3).all)
+    User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a)
+    User.add_to_project(user, p2, Role.where(:id => 3).to_a)
     TimeEntry.generate!(
       :issue => Issue.generate!(:project => p1, :tracker_id => 1,
                                 :custom_field_values => {@field2.id => 'ValueA'}))
@@ -108,9 +108,9 @@ class TimelogCustomFieldsVisibilityTest < ActionController::TestCase
                                 :custom_field_values => {@field2.id => 'ValueC'}))
     @request.session[:user_id] = user.id
     get :index, :c => ["hours", "issue.cf_#{@field2.id}"]
-    assert_select 'td', :text => 'ValueA'
+    assert_select 'td', {:text => 'ValueA'}, "ValueA not found in:\n#{response.body}"
     assert_select 'td', :text => 'ValueB', :count => 0
-    assert_select 'td', :text => 'ValueC'
+    assert_select 'td', {:text => 'ValueC'}, "ValueC not found in:\n#{response.body}"
 
     get :index, :set_filter => '1', "issue.cf_#{@field2.id}" => '*'
     assert_equal %w(ValueA ValueC), assigns(:entries).map{|i| i.issue.custom_field_value(@field2)}.sort
diff --git a/test/functional/welcome_controller_test.rb b/test/functional/welcome_controller_test.rb
index 3509183..aa9afae 100644
--- a/test/functional/welcome_controller_test.rb
+++ b/test/functional/welcome_controller_test.rb
@@ -97,9 +97,7 @@ class WelcomeControllerTest < ActionController::TestCase
     @request.session[:user_id] = 2
 
     get :index
-    assert_tag 'script',
-      :attributes => {:type => "text/javascript"},
-      :content => %r{warnLeavingUnsaved}
+    assert_select 'script', :text => %r{warnLeavingUnsaved}
   end
 
   def test_warn_on_leaving_unsaved_turn_off
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index 3e25be0..41f5dab 100644
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -58,7 +58,9 @@ class WikiControllerTest < ActionController::TestCase
   end
 
   def test_show_old_version
-    get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
+    with_settings :default_language => 'en' do
+      get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
+    end
     assert_response :success
     assert_template 'show'
 
@@ -89,7 +91,9 @@ class WikiControllerTest < ActionController::TestCase
   end
 
   def test_show_first_version
-    get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1'
+    with_settings :default_language => 'en' do
+      get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1'
+    end
     assert_response :success
     assert_template 'show'
 
diff --git a/test/functional/workflows_controller_test.rb b/test/functional/workflows_controller_test.rb
index 09cfc12..5885c4e 100644
--- a/test/functional/workflows_controller_test.rb
+++ b/test/functional/workflows_controller_test.rb
@@ -39,8 +39,6 @@ class WorkflowsControllerTest < ActionController::TestCase
     get :edit
     assert_response :success
     assert_template 'edit'
-    assert_not_nil assigns(:roles)
-    assert_not_nil assigns(:trackers)
   end
 
   def test_get_edit_with_role_and_tracker
@@ -57,18 +55,11 @@ class WorkflowsControllerTest < ActionController::TestCase
     assert_equal [2, 3, 5], assigns(:statuses).collect(&:id)
 
     # allowed transitions
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'issue_status[3][5][]',
-                                                 :value => 'always',
-                                                 :checked => 'checked' }
+    assert_select 'input[type=checkbox][name=?][value=1][checked=checked]', 'transitions[3][5][always]'
     # not allowed
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'issue_status[3][2][]',
-                                                 :value => 'always',
-                                                 :checked => nil }
+    assert_select 'input[type=checkbox][name=?][value=1]:not([checked=checked])', 'transitions[3][2][always]'
     # unused
-    assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                    :name => 'issue_status[1][1][]' }
+    assert_select 'input[type=checkbox][name=?]', 'transitions[1][1][always]', 0
   end
 
   def test_get_edit_with_role_and_tracker_and_all_statuses
@@ -81,19 +72,18 @@ class WorkflowsControllerTest < ActionController::TestCase
     assert_not_nil assigns(:statuses)
     assert_equal IssueStatus.count, assigns(:statuses).size
 
-    assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
-                                                 :name => 'issue_status[1][1][]',
-                                                 :value => 'always',
-                                                 :checked => nil }
+    assert_select 'input[type=checkbox][name=?]', 'transitions[1][1][always]'
   end
 
   def test_post_edit
+    WorkflowTransition.delete_all
+
     post :edit, :role_id => 2, :tracker_id => 1,
-      :issue_status => {
-        '4' => {'5' => ['always']},
-        '3' => {'1' => ['always'], '2' => ['always']}
+      :transitions => {
+        '4' => {'5' => {'always' => '1'}},
+        '3' => {'1' => {'always' => '1'}, '2' => {'always' => '1'}}
       }
-    assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1'
+    assert_response 302
 
     assert_equal 3, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
     assert_not_nil  WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).first
@@ -101,12 +91,16 @@ class WorkflowsControllerTest < ActionController::TestCase
   end
 
   def test_post_edit_with_additional_transitions
+    WorkflowTransition.delete_all
+  
     post :edit, :role_id => 2, :tracker_id => 1,
-      :issue_status => {
-        '4' => {'5' => ['always']},
-        '3' => {'1' => ['author'], '2' => ['assignee'], '4' => ['author', 'assignee']}
+      :transitions => {
+        '4' => {'5' => {'always' => '1', 'author' => '0', 'assignee' => '0'}},
+        '3' => {'1' => {'always' => '0', 'author' => '1', 'assignee' => '0'},
+                '2' => {'always' => '0', 'author' => '0', 'assignee' => '1'},
+                '4' => {'always' => '0', 'author' => '1', 'assignee' => '1'}}
       }
-    assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1'
+    assert_response 302
 
     assert_equal 4, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
 
@@ -124,20 +118,11 @@ class WorkflowsControllerTest < ActionController::TestCase
     assert w.assignee
   end
 
-  def test_clear_workflow
-    assert WorkflowTransition.where(:role_id => 1, :tracker_id => 2).count > 0
-
-    post :edit, :role_id => 1, :tracker_id => 2
-    assert_equal 0, WorkflowTransition.where(:role_id => 1, :tracker_id => 2).count
-  end
-
   def test_get_permissions
     get :permissions
 
     assert_response :success
     assert_template 'permissions'
-    assert_not_nil assigns(:roles)
-    assert_not_nil assigns(:trackers)
   end
 
   def test_get_permissions_with_role_and_tracker
@@ -150,11 +135,11 @@ class WorkflowsControllerTest < ActionController::TestCase
     assert_response :success
     assert_template 'permissions'
 
-    assert_select 'input[name=role_id][value=1]'
-    assert_select 'input[name=tracker_id][value=2]'
+    assert_select 'input[name=?][value=1]', 'role_id[]'
+    assert_select 'input[name=?][value=2]', 'tracker_id[]'
 
     # Required field
-    assert_select 'select[name=?]', 'permissions[assigned_to_id][2]' do
+    assert_select 'select[name=?]', 'permissions[2][assigned_to_id]' do
       assert_select 'option[value=]'
       assert_select 'option[value=][selected=selected]', 0
       assert_select 'option[value=readonly]', :text => 'Read-only'
@@ -164,7 +149,7 @@ class WorkflowsControllerTest < ActionController::TestCase
     end
 
     # Read-only field
-    assert_select 'select[name=?]', 'permissions[fixed_version_id][3]' do
+    assert_select 'select[name=?]', 'permissions[3][fixed_version_id]' do
       assert_select 'option[value=]'
       assert_select 'option[value=][selected=selected]', 0
       assert_select 'option[value=readonly]', :text => 'Read-only'
@@ -174,7 +159,7 @@ class WorkflowsControllerTest < ActionController::TestCase
     end
 
     # Other field
-    assert_select 'select[name=?]', 'permissions[due_date][3]' do
+    assert_select 'select[name=?]', 'permissions[3][due_date]' do
       assert_select 'option[value=]'
       assert_select 'option[value=][selected=selected]', 0
       assert_select 'option[value=readonly]', :text => 'Read-only'
@@ -193,7 +178,7 @@ class WorkflowsControllerTest < ActionController::TestCase
 
     # Custom field that is always required
     # The default option is "(Required)"
-    assert_select 'select[name=?]', "permissions[#{cf.id}][3]" do
+    assert_select 'select[name=?]', "permissions[3][#{cf.id}]" do
       assert_select 'option[value=]'
       assert_select 'option[value=readonly]', :text => 'Read-only'
       assert_select 'option[value=required]', 0
@@ -209,31 +194,72 @@ class WorkflowsControllerTest < ActionController::TestCase
     assert_response :success
     assert_template 'permissions'
 
-    assert_select 'select[name=?]:not(.disabled)', "permissions[#{cf1.id}][1]"
-    assert_select 'select[name=?]:not(.disabled)', "permissions[#{cf3.id}][1]"
+    assert_select 'select[name=?]:not(.disabled)', "permissions[1][#{cf1.id}]"
+    assert_select 'select[name=?]:not(.disabled)', "permissions[1][#{cf3.id}]"
 
-    assert_select 'select[name=?][disabled=disabled]', "permissions[#{cf2.id}][1]" do
+    assert_select 'select[name=?][disabled=disabled]', "permissions[1][#{cf2.id}]" do
       assert_select 'option[value=][selected=selected]', :text => 'Hidden'
     end
   end
 
-  def test_get_permissions_with_role_and_tracker_and_all_statuses
+  def test_get_permissions_with_missing_permissions_for_roles_should_default_to_no_change
+    WorkflowPermission.delete_all
+    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
+
+    get :permissions, :role_id => [1, 2], :tracker_id => 2
+    assert_response :success
+
+    assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
+      assert_select 'option[selected]', 1
+      assert_select 'option[selected][value=no_change]'
+    end
+  end
+
+  def test_get_permissions_with_different_permissions_for_roles_should_default_to_no_change
+    WorkflowPermission.delete_all
+    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
+    WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'readonly')
+
+    get :permissions, :role_id => [1, 2], :tracker_id => 2
+    assert_response :success
+
+    assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
+      assert_select 'option[selected]', 1
+      assert_select 'option[selected][value=no_change]'
+    end
+  end
+
+  def test_get_permissions_with_same_permissions_for_roles_should_default_to_permission
+    WorkflowPermission.delete_all
+    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
+    WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
+
+    get :permissions, :role_id => [1, 2], :tracker_id => 2
+    assert_response :success
+
+    assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
+      assert_select 'option[selected]', 1
+      assert_select 'option[selected][value=required]'
+    end
+  end
+
+  def test_get_permissions_with_role_and_tracker_and_all_statuses_should_show_all_statuses
     WorkflowTransition.delete_all
 
     get :permissions, :role_id => 1, :tracker_id => 2, :used_statuses_only => '0'
     assert_response :success
-    assert_equal IssueStatus.sorted.all, assigns(:statuses)
+    assert_equal IssueStatus.sorted.to_a, assigns(:statuses)
   end
 
   def test_post_permissions
     WorkflowPermission.delete_all
 
     post :permissions, :role_id => 1, :tracker_id => 2, :permissions => {
-      'assigned_to_id' => {'1' => '', '2' => 'readonly', '3' => ''},
-      'fixed_version_id' => {'1' => 'required', '2' => 'readonly', '3' => ''},
-      'due_date' => {'1' => '', '2' => '', '3' => ''},
+      '1' => {'assigned_to_id' => '', 'fixed_version_id' => 'required', 'due_date' => ''},
+      '2' => {'assigned_to_id' => 'readonly', 'fixed_version_id' => 'readonly', 'due_date' => ''},
+      '3' => {'assigned_to_id' => '',  'fixed_version_id' => '', 'due_date' => ''}
     }
-    assert_redirected_to '/workflows/permissions?role_id=1&tracker_id=2'
+    assert_response 302
 
     workflows = WorkflowPermission.all
     assert_equal 3, workflows.size
@@ -246,22 +272,6 @@ class WorkflowsControllerTest < ActionController::TestCase
     assert workflows.detect {|wf| wf.old_status_id == 2 && wf.field_name == 'fixed_version_id' && wf.rule == 'readonly'}
   end
 
-  def test_post_permissions_should_clear_permissions
-    WorkflowPermission.delete_all
-    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'assigned_to_id', :rule => 'required')
-    WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
-    wf1 = WorkflowPermission.create!(:role_id => 1, :tracker_id => 3, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
-    wf2 = WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 3, :field_name => 'fixed_version_id', :rule => 'readonly')
-
-    post :permissions, :role_id => 1, :tracker_id => 2
-    assert_redirected_to '/workflows/permissions?role_id=1&tracker_id=2'
-
-    workflows = WorkflowPermission.all
-    assert_equal 2, workflows.size
-    assert wf1.reload
-    assert wf2.reload
-  end
-
   def test_get_copy
     get :copy
     assert_response :success
diff --git a/test/integration/account_test.rb b/test/integration/account_test.rb
index 8e2c0ec..63320b7 100644
--- a/test/integration/account_test.rb
+++ b/test/integration/account_test.rb
@@ -17,16 +17,9 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-begin
-  require 'mocha/setup'
-rescue
-  # Won't run some tests
-end
-
-class AccountTest < ActionController::IntegrationTest
+class AccountTest < ActionDispatch::IntegrationTest
   fixtures :users, :roles
 
-  # Replace this with your real tests.
   def test_login
     get "my/page"
     assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fmy%2Fpage"
diff --git a/test/integration/admin_test.rb b/test/integration/admin_test.rb
index eebdf10..3b60f0c 100644
--- a/test/integration/admin_test.rb
+++ b/test/integration/admin_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class AdminTest < ActionController::IntegrationTest
+class AdminTest < ActionDispatch::IntegrationTest
   fixtures :projects, :trackers, :issue_statuses, :issues,
            :enumerations, :users, :issue_categories,
            :projects_trackers,
diff --git a/test/integration/api_test/authentication_test.rb b/test/integration/api_test/authentication_test.rb
index 16c589d..b8c9e07 100644
--- a/test/integration/api_test/authentication_test.rb
+++ b/test/integration/api_test/authentication_test.rb
@@ -41,11 +41,8 @@ class Redmine::ApiTest::AuthenticationTest < Redmine::ApiTest::Base
   end
 
   def test_invalid_utf8_credentials_should_not_trigger_an_error
-    invalid_utf8 = "\x82"
-    if invalid_utf8.respond_to?(:force_encoding)
-      invalid_utf8.force_encoding('UTF-8') 
-      assert !invalid_utf8.valid_encoding?
-    end
+    invalid_utf8 = "\x82".force_encoding('UTF-8')
+    assert !invalid_utf8.valid_encoding?
     assert_nothing_raised do
       get '/users/current.xml', {}, credentials(invalid_utf8, "foo")
     end
diff --git a/test/integration/api_test/memberships_test.rb b/test/integration/api_test/memberships_test.rb
index 5446265..eabc394 100644
--- a/test/integration/api_test/memberships_test.rb
+++ b/test/integration/api_test/memberships_test.rb
@@ -155,7 +155,7 @@ class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base
 
     assert_response :unprocessable_entity
     assert_equal 'application/xml', @response.content_type
-    assert_tag 'errors', :child => {:tag => 'error', :content => /member_roles is invalid/}
+    assert_tag 'errors', :child => {:tag => 'error', :content => /role can't be empty/i}
   end
 
   test "DELETE /memberships/:id.xml should destroy the membership" do
diff --git a/test/integration/api_test/projects_test.rb b/test/integration/api_test/projects_test.rb
index 9f63e33..bef0671 100644
--- a/test/integration/api_test/projects_test.rb
+++ b/test/integration/api_test/projects_test.rb
@@ -131,12 +131,12 @@ class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base
   end
 
   test "POST /projects.xml with valid parameters should create the project" do
-    Setting.default_projects_modules = ['issue_tracking', 'repository']
-
-    assert_difference('Project.count') do
-      post '/projects.xml',
-        {:project => {:name => 'API test', :identifier => 'api-test'}},
-        credentials('admin')
+    with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
+      assert_difference('Project.count') do
+        post '/projects.xml',
+          {:project => {:name => 'API test', :identifier => 'api-test'}},
+          credentials('admin')
+      end
     end
 
     project = Project.order('id DESC').first
diff --git a/test/integration/application_test.rb b/test/integration/application_test.rb
index 6b5419d..ced1783 100644
--- a/test/integration/application_test.rb
+++ b/test/integration/application_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class ApplicationTest < ActionController::IntegrationTest
+class ApplicationTest < ActionDispatch::IntegrationTest
   include Redmine::I18n
 
   fixtures :projects, :trackers, :issue_statuses, :issues,
diff --git a/test/integration/attachments_test.rb b/test/integration/attachments_test.rb
index 1a2b92d..69d42d4 100644
--- a/test/integration/attachments_test.rb
+++ b/test/integration/attachments_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class AttachmentsTest < ActionController::IntegrationTest
+class AttachmentsTest < ActionDispatch::IntegrationTest
   fixtures :projects, :enabled_modules,
            :users, :roles, :members, :member_roles,
            :trackers, :projects_trackers,
diff --git a/test/integration/feeds_test.rb b/test/integration/feeds_test.rb
index 0a5e369..160174f 100644
--- a/test/integration/feeds_test.rb
+++ b/test/integration/feeds_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class FeedsTest < ActionController::IntegrationTest
+class FeedsTest < ActionDispatch::IntegrationTest
   fixtures :projects, :trackers, :issue_statuses, :issues,
            :enumerations, :users, :issue_categories,
            :projects_trackers, :enabled_modules,
diff --git a/test/integration/issues_test.rb b/test/integration/issues_test.rb
index 196f16f..b187536 100644
--- a/test/integration/issues_test.rb
+++ b/test/integration/issues_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class IssuesTest < ActionController::IntegrationTest
+class IssuesTest < ActionDispatch::IntegrationTest
   fixtures :projects,
            :users,
            :roles,
diff --git a/test/integration/layout_test.rb b/test/integration/layout_test.rb
index c5284bd..9c03a56 100644
--- a/test/integration/layout_test.rb
+++ b/test/integration/layout_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class LayoutTest < ActionController::IntegrationTest
+class LayoutTest < ActionDispatch::IntegrationTest
   fixtures :projects, :trackers, :issue_statuses, :issues,
            :enumerations, :users, :issue_categories,
            :projects_trackers,
diff --git a/test/integration/lib/redmine/hook_test.rb b/test/integration/lib/redmine/hook_test.rb
index e7f4d1d..b629aa9 100644
--- a/test/integration/lib/redmine/hook_test.rb
+++ b/test/integration/lib/redmine/hook_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../../test_helper', __FILE__)
 
-class HookTest < ActionController::IntegrationTest
+class HookTest < ActionDispatch::IntegrationTest
   fixtures :users, :roles, :projects, :members, :member_roles
 
   # Hooks that are manually registered later
@@ -34,6 +34,8 @@ class HookTest < ActionController::IntegrationTest
     end
   end
 
+  Redmine::Hook.clear_listeners
+
   class ContentForInsideHook < Redmine::Hook::ViewListener
     render_on :view_welcome_index_left, :inline => <<-VIEW
 <% content_for :header_tags do %>
diff --git a/test/integration/lib/redmine/menu_manager_test.rb b/test/integration/lib/redmine/menu_manager_test.rb
index 1699a2a..5d3826a 100644
--- a/test/integration/lib/redmine/menu_manager_test.rb
+++ b/test/integration/lib/redmine/menu_manager_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../../test_helper', __FILE__)
 
-class MenuManagerTest < ActionController::IntegrationTest
+class MenuManagerTest < ActionDispatch::IntegrationTest
   include Redmine::I18n
 
   fixtures :projects, :trackers, :issue_statuses, :issues,
diff --git a/test/integration/lib/redmine/themes_test.rb b/test/integration/lib/redmine/themes_test.rb
index 32c7792..f0d422c 100644
--- a/test/integration/lib/redmine/themes_test.rb
+++ b/test/integration/lib/redmine/themes_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../../test_helper', __FILE__)
 
-class ThemesTest < ActionController::IntegrationTest
+class ThemesTest < ActionDispatch::IntegrationTest
 
   def setup
     @theme = Redmine::Themes.themes.last
diff --git a/test/integration/projects_test.rb b/test/integration/projects_test.rb
index 06499a4..fcbf71d 100644
--- a/test/integration/projects_test.rb
+++ b/test/integration/projects_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class ProjectsTest < ActionController::IntegrationTest
+class ProjectsTest < ActionDispatch::IntegrationTest
   fixtures :projects, :users, :members, :enabled_modules
 
   def test_archive_project
diff --git a/test/integration/repositories_git_test.rb b/test/integration/repositories_git_test.rb
index 18f3b7e..14c7d08 100644
--- a/test/integration/repositories_git_test.rb
+++ b/test/integration/repositories_git_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class RepositoriesGitTest < ActionController::IntegrationTest
+class RepositoriesGitTest < ActionDispatch::IntegrationTest
   fixtures :projects, :users, :roles, :members, :member_roles,
            :repositories, :enabled_modules
 
diff --git a/test/integration/routing/account_test.rb b/test/integration/routing/account_test.rb
index 7f6a9c9..c6d331e 100644
--- a/test/integration/routing/account_test.rb
+++ b/test/integration/routing/account_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingAccountTest < ActionController::IntegrationTest
+class RoutingAccountTest < ActionDispatch::IntegrationTest
   def test_account
     ["get", "post"].each do |method|
       assert_routing(
diff --git a/test/integration/routing/activities_test.rb b/test/integration/routing/activities_test.rb
index 4cab5fb..d5b543f 100644
--- a/test/integration/routing/activities_test.rb
+++ b/test/integration/routing/activities_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingActivitiesTest < ActionController::IntegrationTest
+class RoutingActivitiesTest < ActionDispatch::IntegrationTest
   def test_activities
     assert_routing(
            { :method => 'get', :path => "/activity" },
diff --git a/test/integration/routing/admin_test.rb b/test/integration/routing/admin_test.rb
index 6e9f90f..553ebd6 100644
--- a/test/integration/routing/admin_test.rb
+++ b/test/integration/routing/admin_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingAdminTest < ActionController::IntegrationTest
+class RoutingAdminTest < ActionDispatch::IntegrationTest
   def test_administration_panel
     assert_routing(
         { :method => 'get', :path => "/admin" },
diff --git a/test/integration/routing/attachments_test.rb b/test/integration/routing/attachments_test.rb
index 1d7aabe..2d5f032 100644
--- a/test/integration/routing/attachments_test.rb
+++ b/test/integration/routing/attachments_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingAttachmentsTest < ActionController::IntegrationTest
+class RoutingAttachmentsTest < ActionDispatch::IntegrationTest
   def test_attachments
     assert_routing(
            { :method => 'get', :path => "/attachments/1" },
diff --git a/test/integration/routing/auth_sources_test.rb b/test/integration/routing/auth_sources_test.rb
index 8b73f1f..1a96050 100644
--- a/test/integration/routing/auth_sources_test.rb
+++ b/test/integration/routing/auth_sources_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingAuthSourcesTest < ActionController::IntegrationTest
+class RoutingAuthSourcesTest < ActionDispatch::IntegrationTest
   def test_auth_sources
     assert_routing(
         { :method => 'get', :path => "/auth_sources" },
diff --git a/test/integration/routing/auto_completes_test.rb b/test/integration/routing/auto_completes_test.rb
index c767fcf..4b717fc 100644
--- a/test/integration/routing/auto_completes_test.rb
+++ b/test/integration/routing/auto_completes_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingAutoCompletesTest < ActionController::IntegrationTest
+class RoutingAutoCompletesTest < ActionDispatch::IntegrationTest
   def test_auto_completes
     assert_routing(
         { :method => 'get', :path => "/issues/auto_complete" },
diff --git a/test/integration/routing/boards_test.rb b/test/integration/routing/boards_test.rb
index d730f37..6551181 100644
--- a/test/integration/routing/boards_test.rb
+++ b/test/integration/routing/boards_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingBoardsTest < ActionController::IntegrationTest
+class RoutingBoardsTest < ActionDispatch::IntegrationTest
   def test_boards
     assert_routing(
         { :method => 'get', :path => "/projects/world_domination/boards" },
diff --git a/test/integration/routing/calendars_test.rb b/test/integration/routing/calendars_test.rb
index ddb384c..9e8dfd1 100644
--- a/test/integration/routing/calendars_test.rb
+++ b/test/integration/routing/calendars_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingCalendarsTest < ActionController::IntegrationTest
+class RoutingCalendarsTest < ActionDispatch::IntegrationTest
   def test_calendars
     assert_routing(
         { :method => 'get', :path => "/issues/calendar" },
diff --git a/test/integration/routing/comments_test.rb b/test/integration/routing/comments_test.rb
index 94e33c7..cd5e259 100644
--- a/test/integration/routing/comments_test.rb
+++ b/test/integration/routing/comments_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingCommentsTest < ActionController::IntegrationTest
+class RoutingCommentsTest < ActionDispatch::IntegrationTest
   def test_comments
     assert_routing(
         { :method => 'post', :path => "/news/567/comments" },
diff --git a/test/integration/routing/context_menus_test.rb b/test/integration/routing/context_menus_test.rb
index 1d4be08..caee1ca 100644
--- a/test/integration/routing/context_menus_test.rb
+++ b/test/integration/routing/context_menus_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingContextMenusTest < ActionController::IntegrationTest
+class RoutingContextMenusTest < ActionDispatch::IntegrationTest
   def test_context_menus_time_entries
     ["get", "post"].each do |method|
       assert_routing(
diff --git a/test/integration/routing/custom_fields_test.rb b/test/integration/routing/custom_fields_test.rb
index c1901d8..6649ecf 100644
--- a/test/integration/routing/custom_fields_test.rb
+++ b/test/integration/routing/custom_fields_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingCustomFieldsTest < ActionController::IntegrationTest
+class RoutingCustomFieldsTest < ActionDispatch::IntegrationTest
   def test_custom_fields
     assert_routing(
         { :method => 'get', :path => "/custom_fields" },
diff --git a/test/integration/routing/documents_test.rb b/test/integration/routing/documents_test.rb
index 285f64f..5efbeb1 100644
--- a/test/integration/routing/documents_test.rb
+++ b/test/integration/routing/documents_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingDocumentsTest < ActionController::IntegrationTest
+class RoutingDocumentsTest < ActionDispatch::IntegrationTest
   def test_documents_scoped_under_project
     assert_routing(
         { :method => 'get', :path => "/projects/567/documents" },
diff --git a/test/integration/routing/enumerations_test.rb b/test/integration/routing/enumerations_test.rb
index 9b06764..8b577e1 100644
--- a/test/integration/routing/enumerations_test.rb
+++ b/test/integration/routing/enumerations_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingEnumerationsTest < ActionController::IntegrationTest
+class RoutingEnumerationsTest < ActionDispatch::IntegrationTest
   def test_enumerations
     assert_routing(
         { :method => 'get', :path => "/enumerations" },
diff --git a/test/integration/routing/files_test.rb b/test/integration/routing/files_test.rb
index 9f5c8de..ea6a5aa 100644
--- a/test/integration/routing/files_test.rb
+++ b/test/integration/routing/files_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingFilesTest < ActionController::IntegrationTest
+class RoutingFilesTest < ActionDispatch::IntegrationTest
   def test_files
     assert_routing(
         { :method => 'get', :path => "/projects/33/files" },
diff --git a/test/integration/routing/gantts_test.rb b/test/integration/routing/gantts_test.rb
index e9448ed..c2c626c 100644
--- a/test/integration/routing/gantts_test.rb
+++ b/test/integration/routing/gantts_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingGanttsTest < ActionController::IntegrationTest
+class RoutingGanttsTest < ActionDispatch::IntegrationTest
   def test_gantts
     assert_routing(
         { :method => 'get', :path => "/issues/gantt" },
diff --git a/test/integration/routing/groups_test.rb b/test/integration/routing/groups_test.rb
index cef3887..c89d9c9 100644
--- a/test/integration/routing/groups_test.rb
+++ b/test/integration/routing/groups_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingGroupsTest < ActionController::IntegrationTest
+class RoutingGroupsTest < ActionDispatch::IntegrationTest
   def test_groups_resources
     assert_routing(
         { :method => 'get', :path => "/groups" },
diff --git a/test/integration/routing/issue_categories_test.rb b/test/integration/routing/issue_categories_test.rb
index 537847b..10f23ba 100644
--- a/test/integration/routing/issue_categories_test.rb
+++ b/test/integration/routing/issue_categories_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingIssueCategoriesTest < ActionController::IntegrationTest
+class RoutingIssueCategoriesTest < ActionDispatch::IntegrationTest
   def test_issue_categories_scoped_under_project
     assert_routing(
         { :method => 'get', :path => "/projects/foo/issue_categories" },
diff --git a/test/integration/routing/issue_relations_test.rb b/test/integration/routing/issue_relations_test.rb
index 0588c35..a9bcbf6 100644
--- a/test/integration/routing/issue_relations_test.rb
+++ b/test/integration/routing/issue_relations_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingIssueRelationsTest < ActionController::IntegrationTest
+class RoutingIssueRelationsTest < ActionDispatch::IntegrationTest
   def test_issue_relations
     assert_routing(
         { :method => 'get', :path => "/issues/1/relations" },
diff --git a/test/integration/routing/issue_statuses_test.rb b/test/integration/routing/issue_statuses_test.rb
index f03b966..550fe93 100644
--- a/test/integration/routing/issue_statuses_test.rb
+++ b/test/integration/routing/issue_statuses_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingIssueStatusesTest < ActionController::IntegrationTest
+class RoutingIssueStatusesTest < ActionDispatch::IntegrationTest
   def test_issue_statuses
     assert_routing(
         { :method => 'get', :path => "/issue_statuses" },
diff --git a/test/integration/routing/issues_test.rb b/test/integration/routing/issues_test.rb
index 0c7328a..0dc3c16 100644
--- a/test/integration/routing/issues_test.rb
+++ b/test/integration/routing/issues_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingIssuesTest < ActionController::IntegrationTest
+class RoutingIssuesTest < ActionDispatch::IntegrationTest
   def test_issues_rest_actions
     assert_routing(
         { :method => 'get', :path => "/issues" },
diff --git a/test/integration/routing/journals_test.rb b/test/integration/routing/journals_test.rb
index 0731163..390e774 100644
--- a/test/integration/routing/journals_test.rb
+++ b/test/integration/routing/journals_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingJournalsTest < ActionController::IntegrationTest
+class RoutingJournalsTest < ActionDispatch::IntegrationTest
   def test_journals
     assert_routing(
         { :method => 'post', :path => "/issues/1/quoted" },
diff --git a/test/integration/routing/mail_handler_test.rb b/test/integration/routing/mail_handler_test.rb
index 8ff55b1..8abb536 100644
--- a/test/integration/routing/mail_handler_test.rb
+++ b/test/integration/routing/mail_handler_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingMailHandlerTest < ActionController::IntegrationTest
+class RoutingMailHandlerTest < ActionDispatch::IntegrationTest
   def test_mail_handler
     assert_routing(
         { :method => "post", :path => "/mail_handler" },
diff --git a/test/integration/routing/members_test.rb b/test/integration/routing/members_test.rb
index e249af7..20de566 100644
--- a/test/integration/routing/members_test.rb
+++ b/test/integration/routing/members_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingMembersTest < ActionController::IntegrationTest
+class RoutingMembersTest < ActionDispatch::IntegrationTest
   def test_members
     assert_routing(
         { :method => 'get', :path => "/projects/5234/memberships.xml" },
diff --git a/test/integration/routing/messages_test.rb b/test/integration/routing/messages_test.rb
index a6b8488..696bc86 100644
--- a/test/integration/routing/messages_test.rb
+++ b/test/integration/routing/messages_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingMessagesTest < ActionController::IntegrationTest
+class RoutingMessagesTest < ActionDispatch::IntegrationTest
   def test_messages
     assert_routing(
         { :method => 'get', :path => "/boards/22/topics/2" },
diff --git a/test/integration/routing/my_test.rb b/test/integration/routing/my_test.rb
index 230babc..0f5f3e2 100644
--- a/test/integration/routing/my_test.rb
+++ b/test/integration/routing/my_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingMyTest < ActionController::IntegrationTest
+class RoutingMyTest < ActionDispatch::IntegrationTest
   def test_my
     ["get", "post"].each do |method|
       assert_routing(
diff --git a/test/integration/routing/news_test.rb b/test/integration/routing/news_test.rb
index a5843d5..a1ee7b1 100644
--- a/test/integration/routing/news_test.rb
+++ b/test/integration/routing/news_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingNewsTest < ActionController::IntegrationTest
+class RoutingNewsTest < ActionDispatch::IntegrationTest
   def test_news_index
     assert_routing(
         { :method => 'get', :path => "/news" },
diff --git a/test/integration/routing/previews_test.rb b/test/integration/routing/previews_test.rb
index f0f4e52..fcdcfe5 100644
--- a/test/integration/routing/previews_test.rb
+++ b/test/integration/routing/previews_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingPreviewsTest < ActionController::IntegrationTest
+class RoutingPreviewsTest < ActionDispatch::IntegrationTest
   def test_previews
     ["get", "post", "put"].each do |method|
       assert_routing(
diff --git a/test/integration/routing/project_enumerations_test.rb b/test/integration/routing/project_enumerations_test.rb
index 4065d0b..3eda2c4 100644
--- a/test/integration/routing/project_enumerations_test.rb
+++ b/test/integration/routing/project_enumerations_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingProjectEnumerationsTest < ActionController::IntegrationTest
+class RoutingProjectEnumerationsTest < ActionDispatch::IntegrationTest
   def test_project_enumerations
     assert_routing(
         { :method => 'put', :path => "/projects/64/enumerations" },
diff --git a/test/integration/routing/projects_test.rb b/test/integration/routing/projects_test.rb
index eb33193..392b871 100644
--- a/test/integration/routing/projects_test.rb
+++ b/test/integration/routing/projects_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingProjectsTest < ActionController::IntegrationTest
+class RoutingProjectsTest < ActionDispatch::IntegrationTest
   def test_projects
     assert_routing(
         { :method => 'get', :path => "/projects" },
diff --git a/test/integration/routing/queries_test.rb b/test/integration/routing/queries_test.rb
index f7265a8..ac50fbc 100644
--- a/test/integration/routing/queries_test.rb
+++ b/test/integration/routing/queries_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingQueriesTest < ActionController::IntegrationTest
+class RoutingQueriesTest < ActionDispatch::IntegrationTest
   def test_queries
     assert_routing(
         { :method => 'get', :path => "/queries.xml" },
diff --git a/test/integration/routing/reports_test.rb b/test/integration/routing/reports_test.rb
index db8a865..2483682 100644
--- a/test/integration/routing/reports_test.rb
+++ b/test/integration/routing/reports_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingReportsTest < ActionController::IntegrationTest
+class RoutingReportsTest < ActionDispatch::IntegrationTest
   def test_reports
     assert_routing(
         { :method => 'get', :path => "/projects/567/issues/report" },
diff --git a/test/integration/routing/repositories_test.rb b/test/integration/routing/repositories_test.rb
index c5c6ee2..0e46cb9 100644
--- a/test/integration/routing/repositories_test.rb
+++ b/test/integration/routing/repositories_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingRepositoriesTest < ActionController::IntegrationTest
+class RoutingRepositoriesTest < ActionDispatch::IntegrationTest
   def setup
     @path_hash  = repository_path_hash(%w[path to file.c])
     assert_equal "path/to/file.c", @path_hash[:path]
diff --git a/test/integration/routing/roles_test.rb b/test/integration/routing/roles_test.rb
index 962edcb..5541984 100644
--- a/test/integration/routing/roles_test.rb
+++ b/test/integration/routing/roles_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingRolesTest < ActionController::IntegrationTest
+class RoutingRolesTest < ActionDispatch::IntegrationTest
   def test_roles
     assert_routing(
         { :method => 'get', :path => "/roles" },
diff --git a/test/integration/routing/search_test.rb b/test/integration/routing/search_test.rb
index 96c2ac2..6ea40fd 100644
--- a/test/integration/routing/search_test.rb
+++ b/test/integration/routing/search_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingSearchTest < ActionController::IntegrationTest
+class RoutingSearchTest < ActionDispatch::IntegrationTest
   def test_search
     assert_routing(
         { :method => 'get', :path => "/search" },
diff --git a/test/integration/routing/settings_test.rb b/test/integration/routing/settings_test.rb
index c36989c..4cc986d 100644
--- a/test/integration/routing/settings_test.rb
+++ b/test/integration/routing/settings_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingSettingsTest < ActionController::IntegrationTest
+class RoutingSettingsTest < ActionDispatch::IntegrationTest
   def test_settings
     assert_routing(
         { :method => 'get', :path => "/settings" },
diff --git a/test/integration/routing/sys_test.rb b/test/integration/routing/sys_test.rb
index 1f69ddc..1efe032 100644
--- a/test/integration/routing/sys_test.rb
+++ b/test/integration/routing/sys_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingSysTest < ActionController::IntegrationTest
+class RoutingSysTest < ActionDispatch::IntegrationTest
   def test_sys
     assert_routing(
         { :method => 'get', :path => "/sys/projects" },
diff --git a/test/integration/routing/timelog_test.rb b/test/integration/routing/timelog_test.rb
index eaba22c..0b36bb6 100644
--- a/test/integration/routing/timelog_test.rb
+++ b/test/integration/routing/timelog_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingTimelogsTest < ActionController::IntegrationTest
+class RoutingTimelogsTest < ActionDispatch::IntegrationTest
   def test_timelogs_global
     assert_routing(
         { :method => 'get', :path => "/time_entries" },
diff --git a/test/integration/routing/trackers_test.rb b/test/integration/routing/trackers_test.rb
index afefbee..338197d 100644
--- a/test/integration/routing/trackers_test.rb
+++ b/test/integration/routing/trackers_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingTrackersTest < ActionController::IntegrationTest
+class RoutingTrackersTest < ActionDispatch::IntegrationTest
   def test_trackers
     assert_routing(
         { :method => 'get', :path => "/trackers" },
diff --git a/test/integration/routing/users_test.rb b/test/integration/routing/users_test.rb
index db9a8dd..dbdcbcc 100644
--- a/test/integration/routing/users_test.rb
+++ b/test/integration/routing/users_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingUsersTest < ActionController::IntegrationTest
+class RoutingUsersTest < ActionDispatch::IntegrationTest
   def test_users
     assert_routing(
         { :method => 'get', :path => "/users" },
diff --git a/test/integration/routing/versions_test.rb b/test/integration/routing/versions_test.rb
index d347603..28a7969 100644
--- a/test/integration/routing/versions_test.rb
+++ b/test/integration/routing/versions_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingVersionsTest < ActionController::IntegrationTest
+class RoutingVersionsTest < ActionDispatch::IntegrationTest
   def test_roadmap
     # /projects/foo/versions is /projects/foo/roadmap
     assert_routing(
diff --git a/test/integration/routing/watchers_test.rb b/test/integration/routing/watchers_test.rb
index 2715d77..be35d56 100644
--- a/test/integration/routing/watchers_test.rb
+++ b/test/integration/routing/watchers_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingWatchersTest < ActionController::IntegrationTest
+class RoutingWatchersTest < ActionDispatch::IntegrationTest
   def test_watchers
     assert_routing(
         { :method => 'get', :path => "/watchers/new" },
diff --git a/test/integration/routing/welcome_test.rb b/test/integration/routing/welcome_test.rb
index f873002..2c2a322 100644
--- a/test/integration/routing/welcome_test.rb
+++ b/test/integration/routing/welcome_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingWelcomeTest < ActionController::IntegrationTest
+class RoutingWelcomeTest < ActionDispatch::IntegrationTest
   def test_welcome
     assert_routing(
         { :method => 'get', :path => "/" },
diff --git a/test/integration/routing/wiki_test.rb b/test/integration/routing/wiki_test.rb
index 0d19247..f677856 100644
--- a/test/integration/routing/wiki_test.rb
+++ b/test/integration/routing/wiki_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingWikiTest < ActionController::IntegrationTest
+class RoutingWikiTest < ActionDispatch::IntegrationTest
   def test_wiki_matching
     assert_routing(
         { :method => 'get', :path => "/projects/567/wiki" },
@@ -54,7 +54,7 @@ class RoutingWikiTest < ActionController::IntegrationTest
            :id => 'CookBook_documentation', :version => '2' }
        )
     # Make sure we don't route wiki page sub-uris to let plugins handle them
-    assert_raise(ActionController::RoutingError) do
+    assert_raise(Minitest::Assertion) do
       assert_recognizes({}, {:method => 'get', :path => "/projects/1/wiki/CookBook_documentation/whatever"})
     end
   end
diff --git a/test/integration/routing/wikis_test.rb b/test/integration/routing/wikis_test.rb
index 1fbc672..98c83d0 100644
--- a/test/integration/routing/wikis_test.rb
+++ b/test/integration/routing/wikis_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingWikisTest < ActionController::IntegrationTest
+class RoutingWikisTest < ActionDispatch::IntegrationTest
   def test_wikis_plural_admin_setup
     ["get", "post"].each do |method|
       assert_routing(
diff --git a/test/integration/routing/workflows_test.rb b/test/integration/routing/workflows_test.rb
index cfa19a2..828b827 100644
--- a/test/integration/routing/workflows_test.rb
+++ b/test/integration/routing/workflows_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../../test_helper', __FILE__)
 
-class RoutingWorkflowsTest < ActionController::IntegrationTest
+class RoutingWorkflowsTest < ActionDispatch::IntegrationTest
   def test_workflows
     assert_routing(
         { :method => 'get', :path => "/workflows" },
diff --git a/test/integration/users_test.rb b/test/integration/users_test.rb
index 9b309c1..de5e35e 100644
--- a/test/integration/users_test.rb
+++ b/test/integration/users_test.rb
@@ -17,7 +17,7 @@
 
 require File.expand_path('../../test_helper', __FILE__)
 
-class UsersTest < ActionController::IntegrationTest
+class UsersTest < ActionDispatch::IntegrationTest
   fixtures :users
 
   def test_destroy_should_not_accept_get_requests
diff --git a/test/object_helpers.rb b/test/object_helpers.rb
index 1f58baf..1469e6a 100644
--- a/test/object_helpers.rb
+++ b/test/object_helpers.rb
@@ -14,7 +14,7 @@ module ObjectHelpers
 
   def User.add_to_project(user, project, roles=nil)
     roles = Role.find(1) if roles.nil?
-    roles = [roles] unless roles.is_a?(Array)
+    roles = [roles] if roles.is_a?(Role)
     Member.create!(:principal => user, :project => project, :roles => roles)
   end
 
diff --git a/test/test_helper.rb b/test/test_helper.rb
index bc1a350..3e1a067 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -25,18 +25,27 @@ require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
 include ObjectHelpers
 
 require 'awesome_nested_set/version'
+require 'shoulda'
+
+class ActionView::TestCase
+  helper :application
+  include ApplicationHelper
+end
 
 class ActiveSupport::TestCase
   include ActionDispatch::TestProcess
+  include Shoulda::Context::Assertions
+  include Shoulda::Context::InstanceMethods
+  extend Shoulda::Context::ClassMethods
 
   self.use_transactional_fixtures = true
   self.use_instantiated_fixtures  = false
 
-  ESCAPED_CANT  = 'can&#x27;t'
-  ESCAPED_UCANT = 'Can&#x27;t'
+  #ESCAPED_CANT  = 'can&#x27;t'
+  #ESCAPED_UCANT = 'Can&#x27;t'
   # Rails 4.0.2
-  #ESCAPED_CANT  = 'can't'
-  #ESCAPED_UCANT = 'Can't'
+  ESCAPED_CANT  = 'can't'
+  ESCAPED_UCANT = 'Can't'
 
   def log_user(login, password)
     User.anonymous
@@ -221,7 +230,8 @@ class ActiveSupport::TestCase
   # It seems correct behavior because of this line comment.
   #   https://github.com/collectiveidea/awesome_nested_set/blame/199fca9bb9/lib/awesome_nested_set/model.rb#L278
   def new_issue_lft
-    ::AwesomeNestedSet::VERSION > "2.1.6" ? Issue.maximum(:rgt) + 1 : 1
+    # ::AwesomeNestedSet::VERSION > "2.1.6" ? Issue.maximum(:rgt) + 1 : 1
+    Issue.maximum(:rgt) + 1
   end
 end
 
diff --git a/test/unit/changeset_test.rb b/test/unit/changeset_test.rb
index 5ee5080..8965c48 100644
--- a/test/unit/changeset_test.rb
+++ b/test/unit/changeset_test.rb
@@ -25,7 +25,8 @@ class ChangesetTest < ActiveSupport::TestCase
            :changesets, :changes,
            :enumerations,
            :custom_fields, :custom_values,
-           :users, :members, :member_roles, :trackers,
+           :users, :members, :member_roles,
+           :trackers, :projects_trackers,
            :enabled_modules, :roles
 
   def test_ref_keywords_any
@@ -376,8 +377,7 @@ class ChangesetTest < ActiveSupport::TestCase
   def test_comments_should_be_converted_to_utf8
     proj = Project.find(3)
     # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
-    str = "Texte encod\xe9 en ISO-8859-1."
-    str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
+    str = "Texte encod\xe9 en ISO-8859-1.".force_encoding("ASCII-8BIT")
     r = Repository::Bazaar.create!(
             :project      => proj,
             :url          => '/tmp/test/bazaar',
@@ -389,18 +389,15 @@ class ChangesetTest < ActiveSupport::TestCase
                       :scmid        => '12345',
                       :comments     => str)
     assert( c.save )
-    str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1."
-    str_utf8.force_encoding("UTF-8") if str_utf8.respond_to?(:force_encoding)
+    str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1.".force_encoding("UTF-8")
     assert_equal str_utf8, c.comments
   end
 
   def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1
     proj = Project.find(3)
     # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
-    str1 = "Texte encod\xe9 en ISO-8859-1."
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
+    str1 = "Texte encod\xe9 en ISO-8859-1.".force_encoding("UTF-8")
+    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
     r = Repository::Bazaar.create!(
             :project      => proj,
             :url          => '/tmp/test/bazaar',
@@ -419,10 +416,7 @@ class ChangesetTest < ActiveSupport::TestCase
 
   def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis
     proj = Project.find(3)
-    str = "test\xb5\xfetest\xb5\xfe"
-    if str.respond_to?(:force_encoding)
-      str.force_encoding('ASCII-8BIT')
-    end
+    str = "test\xb5\xfetest\xb5\xfe".force_encoding('ASCII-8BIT')
     r = Repository::Bazaar.create!(
             :project      => proj,
             :url          => '/tmp/test/bazaar',
@@ -441,14 +435,12 @@ class ChangesetTest < ActiveSupport::TestCase
     s1 = "\xC2\x80"
     s2 = "\xc3\x82\xc2\x80"
     s4 = s2.dup
-    if s1.respond_to?(:force_encoding)
-      s3 = s1.dup
-      s1.force_encoding('ASCII-8BIT')
-      s2.force_encoding('ASCII-8BIT')
-      s3.force_encoding('ISO-8859-1')
-      s4.force_encoding('UTF-8')
-      assert_equal s3.encode('UTF-8'), s4
-    end
+    s3 = s1.dup
+    s1.force_encoding('ASCII-8BIT')
+    s2.force_encoding('ASCII-8BIT')
+    s3.force_encoding('ISO-8859-1')
+    s4.force_encoding('UTF-8')
+    assert_equal s3.encode('UTF-8'), s4
     proj = Project.find(3)
     r = Repository::Bazaar.create!(
             :project      => proj,
@@ -466,10 +458,8 @@ class ChangesetTest < ActiveSupport::TestCase
 
   def test_invalid_utf8_sequences_in_paths_should_be_replaced
     proj = Project.find(3)
-    str1 = "Texte encod\xe9 en ISO-8859-1"
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8")      if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
+    str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8")
+    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
     r = Repository::Bazaar.create!(
             :project => proj,
             :url => '/tmp/test/bazaar',
@@ -509,9 +499,7 @@ class ChangesetTest < ActiveSupport::TestCase
     assert( c.save )
     assert_equal "", c.comments
     assert_equal nil, c.committer
-    if c.comments.respond_to?(:force_encoding)
-      assert_equal "UTF-8", c.comments.encoding.to_s
-    end
+    assert_equal "UTF-8", c.comments.encoding.to_s
   end
 
   def test_comments_empty
@@ -530,10 +518,8 @@ class ChangesetTest < ActiveSupport::TestCase
     assert( c.save )
     assert_equal "", c.comments
     assert_equal "", c.committer
-    if c.comments.respond_to?(:force_encoding)
-      assert_equal "UTF-8", c.comments.encoding.to_s
-      assert_equal "UTF-8", c.committer.encoding.to_s
-    end
+    assert_equal "UTF-8", c.comments.encoding.to_s
+    assert_equal "UTF-8", c.committer.encoding.to_s
   end
 
   def test_comments_should_accept_more_than_64k
diff --git a/test/unit/custom_field_test.rb b/test/unit/custom_field_test.rb
index ca94f71..8e8ebe0 100644
--- a/test/unit/custom_field_test.rb
+++ b/test/unit/custom_field_test.rb
@@ -95,14 +95,12 @@ class CustomFieldTest < ActiveSupport::TestCase
     assert_equal ["One value", "And another one"], field.possible_values
   end
 
-  if "string".respond_to?(:encoding)
-    def test_possible_values_stored_as_binary_should_be_utf8_encoded
-      field = CustomField.find(11)
-      assert_kind_of Array, field.possible_values
-      assert field.possible_values.size > 0
-      field.possible_values.each do |value|
-        assert_equal "UTF-8", value.encoding.name
-      end
+  def test_possible_values_stored_as_binary_should_be_utf8_encoded
+    field = CustomField.find(11)
+    assert_kind_of Array, field.possible_values
+    assert field.possible_values.size > 0
+    field.possible_values.each do |value|
+      assert_equal "UTF-8", value.encoding.name
     end
   end
 
diff --git a/test/unit/enabled_module_test.rb b/test/unit/enabled_module_test.rb
index b4c7ace..918d53e 100644
--- a/test/unit/enabled_module_test.rb
+++ b/test/unit/enabled_module_test.rb
@@ -22,7 +22,7 @@ class EnabledModuleTest < ActiveSupport::TestCase
 
   def test_enabling_wiki_should_create_a_wiki
     CustomField.delete_all
-    project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject')
+    project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject', :enabled_module_names => [])
     assert_nil project.wiki
     project.enabled_module_names = ['wiki']
     project.reload
diff --git a/test/unit/group_test.rb b/test/unit/group_test.rb
index 188e946..3013899 100644
--- a/test/unit/group_test.rb
+++ b/test/unit/group_test.rb
@@ -52,8 +52,7 @@ class GroupTest < ActiveSupport::TestCase
 
   def test_blank_name_error_message_fr
     set_language_if_valid 'fr'
-    str = "Nom doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Nom doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     g = Group.new
     assert !g.save
     assert_include str, g.errors.full_messages
diff --git a/test/unit/helpers/application_helper_test.rb b/test/unit/helpers/application_helper_test.rb
index 78de2ac..6ce52ed 100644
--- a/test/unit/helpers/application_helper_test.rb
+++ b/test/unit/helpers/application_helper_test.rb
@@ -26,6 +26,7 @@ class ApplicationHelperTest < ActionView::TestCase
 
   fixtures :projects, :roles, :enabled_modules, :users,
            :repositories, :changesets,
+           :projects_trackers,
            :trackers, :issue_statuses, :issues, :versions, :documents,
            :wikis, :wiki_pages, :wiki_contents,
            :boards, :messages, :news,
@@ -34,10 +35,7 @@ class ApplicationHelperTest < ActionView::TestCase
   def setup
     super
     set_tmp_attachments_directory
-    @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82"
-    if @russian_test.respond_to?(:force_encoding)
-      @russian_test.force_encoding('UTF-8')
-    end
+    @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82".force_encoding('UTF-8')
   end
 
   test "#link_to_if_authorized for authorized user should allow using the :controller and :action for the target link" do
@@ -98,16 +96,12 @@ class ApplicationHelperTest < ActionView::TestCase
     to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
   end
 
-  if 'ruby'.respond_to?(:encoding)
-    def test_auto_links_with_non_ascii_characters
-      to_test = {
-        "http://foo.bar/#{@russian_test}" =>
-          %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>|
-      }
-      to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-    end
-  else
-    puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version'
+  def test_auto_links_with_non_ascii_characters
+    to_test = {
+      "http://foo.bar/#{@russian_test}" =>
+        %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>|
+    }
+    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
   end
 
   def test_auto_mailto
@@ -253,16 +247,12 @@ RAW
     to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
   end
 
-  if 'ruby'.respond_to?(:encoding)
-    def test_textile_external_links_with_non_ascii_characters
-      to_test = {
-        %|This is a "link":http://foo.bar/#{@russian_test}| =>
-          %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>|
-      }
-      to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
-    end
-  else
-    puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version'
+  def test_textile_external_links_with_non_ascii_characters
+    to_test = {
+      %|This is a "link":http://foo.bar/#{@russian_test}| =>
+        %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>|
+    }
+    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
   end
 
   def test_redmine_links
@@ -713,7 +703,7 @@ RAW
           link_to("Unknown page",
                   "/projects/onlinestore/wiki/Unknown_page",
                   :class => "wiki-page new"),
-      # striked through link
+      # struck through link
       '-[[Another page|Page]]-' =>
           "<del>".html_safe +
             link_to("Page",
@@ -1335,13 +1325,8 @@ RAW
     project = Project.find(1)
     assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
                  link_to_project(project)
-    assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
-                 link_to_project(project, :action => 'settings')
     assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
                  link_to_project(project, {:only_path => false, :jump => 'blah'})
-    result = link_to("eCookbook", "/projects/ecookbook/settings", :class => "project")
-    assert_equal result,
-                 link_to_project(project, {:action => 'settings'}, :class => "project")
   end
 
   def test_link_to_project_settings
@@ -1432,7 +1417,7 @@ RAW
 
   def test_raw_json_should_escape_closing_tags
     s = raw_json(["<foo>bar</foo>"])
-    assert_equal '["<foo>bar<\/foo>"]', s
+    assert_include '\/foo', s
   end
 
   def test_raw_json_should_be_html_safe
@@ -1507,8 +1492,7 @@ RAW
   end
 
   def test_truncate_single_line_non_ascii
-    ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
+    ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
     result = truncate_single_line_raw("#{ja}\n#{ja}\n#{ja}", 10)
     assert_equal "#{ja} #{ja}...", result
     assert !result.html_safe?
diff --git a/test/unit/helpers/projects_helper_test.rb b/test/unit/helpers/projects_helper_test.rb
index 02e6fd4..20f4283 100644
--- a/test/unit/helpers/projects_helper_test.rb
+++ b/test/unit/helpers/projects_helper_test.rb
@@ -22,6 +22,7 @@ class ProjectsHelperTest < ActionView::TestCase
   include ProjectsHelper
   include Redmine::I18n
   include ERB::Util
+  include Rails.application.routes.url_helpers
 
   fixtures :projects, :trackers, :issue_statuses, :issues,
            :enumerations, :users, :issue_categories,
diff --git a/test/unit/initializers/patches_test.rb b/test/unit/initializers/patches_test.rb
index ac4b12b..2b761a4 100644
--- a/test/unit/initializers/patches_test.rb
+++ b/test/unit/initializers/patches_test.rb
@@ -47,21 +47,19 @@ class PatchesTest < ActiveSupport::TestCase
   end
 
   # https://github.com/rails/rails/pull/14198/files
-  if RUBY_VERSION >= "1.9"
-    def test_indifferent_select
-      hash = ActiveSupport::HashWithIndifferentAccess.new(@symbols).select { |_ ,v| v == 1 }
-      assert_equal({ 'a' => 1 }, hash)
-      assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ?
-                            Hash : ActiveSupport::HashWithIndifferentAccess),
-                          hash
-    end
+  def test_indifferent_select
+    hash = ActiveSupport::HashWithIndifferentAccess.new(@symbols).select { |_ ,v| v == 1 }
+    assert_equal({ 'a' => 1 }, hash)
+    assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ?
+                          Hash : ActiveSupport::HashWithIndifferentAccess),
+                        hash
+  end
 
-    def test_indifferent_select_bang
-      indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@symbols)
-      indifferent_strings.select! { |_, v| v == 1 }
-      assert_equal({ 'a' => 1 }, indifferent_strings)
-      assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings
-    end
+  def test_indifferent_select_bang
+    indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@symbols)
+    indifferent_strings.select! { |_, v| v == 1 }
+    assert_equal({ 'a' => 1 }, indifferent_strings)
+    assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings
   end
 
   def test_indifferent_reject
@@ -77,15 +75,13 @@ class PatchesTest < ActiveSupport::TestCase
     assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings
   end
 
-  if RUBY_VERSION >= "1.9"
-    def test_select
-      assert_equal @keys, @ordered_hash.select { true }.map(&:first)
-      new_ordered_hash = @ordered_hash.select { true }
-      assert_equal @keys, new_ordered_hash.map(&:first)
-      assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ?
-                            Hash : ActiveSupport::OrderedHash),
-                          new_ordered_hash
-    end
+  def test_select
+    assert_equal @keys, @ordered_hash.select { true }.map(&:first)
+    new_ordered_hash = @ordered_hash.select { true }
+    assert_equal @keys, new_ordered_hash.map(&:first)
+    assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ?
+                          Hash : ActiveSupport::OrderedHash),
+                        new_ordered_hash
   end
 
   def test_reject
diff --git a/test/unit/issue_nested_set_test.rb b/test/unit/issue_nested_set_test.rb
index 495d3b7..d31acde 100644
--- a/test/unit/issue_nested_set_test.rb
+++ b/test/unit/issue_nested_set_test.rb
@@ -86,6 +86,7 @@ class IssueNestedSetTest < ActiveSupport::TestCase
     parent1 = Issue.generate!
     lft2 = new_issue_lft
     parent2 = Issue.generate!
+    lft3 = new_issue_lft
     child = parent1.generate_child!
     child.parent_issue_id = nil
     child.save!
@@ -94,7 +95,7 @@ class IssueNestedSetTest < ActiveSupport::TestCase
     parent2.reload
     assert_equal [parent1.id, lft1, lft1 + 1], [parent1.root_id, parent1.lft, parent1.rgt]
     assert_equal [parent2.id, lft2, lft2 + 1], [parent2.root_id, parent2.lft, parent2.rgt]
-    assert_equal [child.id, 1, 2], [child.root_id, child.lft, child.rgt]
+    assert_equal [child.id,   lft3, lft3 + 1], [child.root_id, child.lft, child.rgt]
   end
 
   def test_move_a_child_to_another_issue
@@ -145,6 +146,7 @@ class IssueNestedSetTest < ActiveSupport::TestCase
     parent1 = Issue.generate!
     child = parent1.generate_child!
     grandchild = child.generate_child!
+    lft4 = new_issue_lft
     child.reload
     child.project = Project.find(2)
     assert child.save
@@ -152,8 +154,10 @@ class IssueNestedSetTest < ActiveSupport::TestCase
     grandchild.reload
     parent1.reload
     assert_equal [1, parent1.id, lft1, lft1 + 1], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
-    assert_equal [2, child.id, 1, 4], [child.project_id, child.root_id, child.lft, child.rgt]
-    assert_equal [2, child.id, 2, 3], [grandchild.project_id, grandchild.root_id, grandchild.lft, grandchild.rgt]
+    assert_equal [2, child.id, lft4, lft4 + 3],
+                 [child.project_id, child.root_id, child.lft, child.rgt]
+    assert_equal [2, child.id, lft4 + 1, lft4 + 2],
+                 [grandchild.project_id, grandchild.root_id, grandchild.lft, grandchild.rgt]
   end
 
   def test_moving_an_issue_to_a_descendant_should_not_validate
@@ -412,7 +416,7 @@ class IssueNestedSetTest < ActiveSupport::TestCase
     c.reload
 
     assert_equal 5, c.issues.count
-    ic1, ic2, ic3, ic4, ic5 = c.issues.order('subject').all
+    ic1, ic2, ic3, ic4, ic5 = c.issues.order('subject').to_a
     assert ic1.root?
     assert_equal ic1, ic2.parent
     assert_equal ic1, ic3.parent
diff --git a/test/unit/issue_priority_test.rb b/test/unit/issue_priority_test.rb
index f9c0c97..7c4a380 100644
--- a/test/unit/issue_priority_test.rb
+++ b/test/unit/issue_priority_test.rb
@@ -83,7 +83,7 @@ class IssuePriorityTest < ActiveSupport::TestCase
     IssuePriority.clear_position_names
 
     IssuePriority.compute_position_names
-    assert_equal %w(lowest default high3 high2 highest), IssuePriority.active.all.sort.map(&:position_name)
+    assert_equal %w(lowest default high3 high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
   end
 
   def test_compute_position_names_without_default_priority_should_split_priorities
@@ -91,16 +91,16 @@ class IssuePriorityTest < ActiveSupport::TestCase
     IssuePriority.update_all :is_default => false
 
     IssuePriority.compute_position_names
-    assert_equal %w(lowest low2 default high2 highest), IssuePriority.active.all.sort.map(&:position_name)
+    assert_equal %w(lowest low2 default high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
   end
 
   def test_adding_a_priority_should_update_position_names
     priority = IssuePriority.create!(:name => 'New')
-    assert_equal %w(lowest default high4 high3 high2 highest), IssuePriority.active.all.sort.map(&:position_name)
+    assert_equal %w(lowest default high4 high3 high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
   end
 
   def test_destroying_a_priority_should_update_position_names
     IssuePriority.find_by_position_name('highest').destroy
-    assert_equal %w(lowest default high2 highest), IssuePriority.active.all.sort.map(&:position_name)
+    assert_equal %w(lowest default high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
   end
 end
diff --git a/test/unit/issue_status_test.rb b/test/unit/issue_status_test.rb
index f9855af..387fa16 100644
--- a/test/unit/issue_status_test.rb
+++ b/test/unit/issue_status_test.rb
@@ -112,7 +112,7 @@ class IssueStatusTest < ActiveSupport::TestCase
   end
 
   def test_sorted_scope
-    assert_equal IssueStatus.all.sort, IssueStatus.sorted.all
+    assert_equal IssueStatus.all.sort, IssueStatus.sorted.to_a
   end
 
   def test_named_scope
diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb
index c4cf77c..0a2425a 100644
--- a/test/unit/issue_test.rb
+++ b/test/unit/issue_test.rb
@@ -204,7 +204,7 @@ class IssueTest < ActiveSupport::TestCase
 
   def test_visible_scope_for_anonymous
     # Anonymous user should see issues of public projects only
-    issues = Issue.visible(User.anonymous).all
+    issues = Issue.visible(User.anonymous).to_a
     assert issues.any?
     assert_nil issues.detect {|issue| !issue.project.is_public?}
     assert_nil issues.detect {|issue| issue.is_private?}
@@ -214,7 +214,7 @@ class IssueTest < ActiveSupport::TestCase
   def test_visible_scope_for_anonymous_without_view_issues_permissions
     # Anonymous user should not see issues without permission
     Role.anonymous.remove_permission!(:view_issues)
-    issues = Issue.visible(User.anonymous).all
+    issues = Issue.visible(User.anonymous).to_a
     assert issues.empty?
     assert_visibility_match User.anonymous, issues
   end
@@ -237,7 +237,7 @@ class IssueTest < ActiveSupport::TestCase
     user = User.find(9)
     assert user.projects.empty?
     # Non member user should see issues of public projects only
-    issues = Issue.visible(user).all
+    issues = Issue.visible(user).to_a
     assert issues.any?
     assert_nil issues.detect {|issue| !issue.project.is_public?}
     assert_nil issues.detect {|issue| issue.is_private?}
@@ -249,7 +249,7 @@ class IssueTest < ActiveSupport::TestCase
     Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
     user = User.find(9)
 
-    issues = Issue.visible(user).all
+    issues = Issue.visible(user).to_a
     assert issues.any?
     assert_nil issues.detect {|issue| issue.author != user}
     assert_visibility_match user, issues
@@ -260,7 +260,7 @@ class IssueTest < ActiveSupport::TestCase
     Role.non_member.remove_permission!(:view_issues)
     user = User.find(9)
     assert user.projects.empty?
-    issues = Issue.visible(user).all
+    issues = Issue.visible(user).to_a
     assert issues.empty?
     assert_visibility_match user, issues
   end
@@ -270,7 +270,7 @@ class IssueTest < ActiveSupport::TestCase
     # User should see issues of projects for which user has view_issues permissions only
     Role.non_member.remove_permission!(:view_issues)
     Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
-    issues = Issue.visible(user).all
+    issues = Issue.visible(user).to_a
     assert issues.any?
     assert_nil issues.detect {|issue| issue.project_id != 3}
     assert_nil issues.detect {|issue| issue.is_private?}
@@ -290,12 +290,12 @@ class IssueTest < ActiveSupport::TestCase
       :is_private => true)
 
     Role.find(2).update_attribute :issues_visibility, 'default'
-    issues = Issue.visible(User.find(8)).all
+    issues = Issue.visible(User.find(8)).to_a
     assert issues.any?
     assert issues.include?(issue)
 
     Role.find(2).update_attribute :issues_visibility, 'own'
-    issues = Issue.visible(User.find(8)).all
+    issues = Issue.visible(User.find(8)).to_a
     assert issues.any?
     assert issues.include?(issue)
   end
@@ -304,7 +304,7 @@ class IssueTest < ActiveSupport::TestCase
     user = User.find(1)
     user.members.each(&:destroy)
     assert user.projects.empty?
-    issues = Issue.visible(user).all
+    issues = Issue.visible(user).to_a
     assert issues.any?
     # Admin should see issues on private projects that admin does not belong to
     assert issues.detect {|issue| !issue.project.is_public?}
@@ -315,7 +315,7 @@ class IssueTest < ActiveSupport::TestCase
 
   def test_visible_scope_with_project
     project = Project.find(1)
-    issues = Issue.visible(User.find(2), :project => project).all
+    issues = Issue.visible(User.find(2), :project => project).to_a
     projects = issues.collect(&:project).uniq
     assert_equal 1, projects.size
     assert_equal project, projects.first
@@ -323,7 +323,7 @@ class IssueTest < ActiveSupport::TestCase
 
   def test_visible_scope_with_project_and_subprojects
     project = Project.find(1)
-    issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
+    issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a
     projects = issues.collect(&:project).uniq
     assert projects.size > 1
     assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
@@ -350,12 +350,12 @@ class IssueTest < ActiveSupport::TestCase
   end
 
   def test_open_scope
-    issues = Issue.open.all
+    issues = Issue.open.to_a
     assert_nil issues.detect(&:closed?)
   end
 
   def test_open_scope_with_arg
-    issues = Issue.open(false).all
+    issues = Issue.open(false).to_a
     assert_equal issues, issues.select(&:closed?)
   end
 
@@ -1268,7 +1268,7 @@ class IssueTest < ActiveSupport::TestCase
   end
 
   test "#copy should not create a journal" do
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
+    copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false)
     copy.save!
     assert_equal 0, copy.reload.journals.size
   end
@@ -1304,7 +1304,7 @@ class IssueTest < ActiveSupport::TestCase
   test "#copy should create a journal with notes" do
     date = Date.today
     notes = "Notes added when copying"
-    copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
+    copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false)
     copy.init_journal(User.current, notes)
     copy.save!
 
@@ -1598,13 +1598,15 @@ class IssueTest < ActiveSupport::TestCase
     issue2.reload
     assert_equal Date.parse('2012-10-18'), issue2.start_date
 
-    child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
-      :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
-    assert !child.valid?
-    assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
-    assert_equal Date.parse('2012-10-18'), child.soonest_start
-    child.start_date = '2012-10-18'
-    assert child.save
+    with_settings :date_format => '%m/%d/%Y' do
+      child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
+        :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
+      assert !child.valid?
+      assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
+      assert_equal Date.parse('2012-10-18'), child.soonest_start
+      child.start_date = '2012-10-18'
+      assert child.save
+    end
   end
 
   def test_setting_parent_to_a_dependent_issue_should_not_validate
diff --git a/test/unit/journal_observer_test.rb b/test/unit/journal_observer_test.rb
index 50c7602..7379fde 100644
--- a/test/unit/journal_observer_test.rb
+++ b/test/unit/journal_observer_test.rb
@@ -31,7 +31,7 @@ class JournalObserverTest < ActiveSupport::TestCase
   def test_create_should_send_email_notification_with_issue_updated
     issue = Issue.first
     user = User.first
-    journal = issue.init_journal(user, issue)
+    journal = issue.init_journal(user, "some notes")
 
     with_settings :notified_events => %w(issue_updated) do
       assert journal.save
@@ -42,7 +42,7 @@ class JournalObserverTest < ActiveSupport::TestCase
   def test_create_should_not_send_email_notification_with_notify_set_to_false
     issue = Issue.first
     user = User.first
-    journal = issue.init_journal(user, issue)
+    journal = issue.init_journal(user, "some notes")
     journal.notify = false
 
     with_settings :notified_events => %w(issue_updated) do
@@ -54,7 +54,7 @@ class JournalObserverTest < ActiveSupport::TestCase
   def test_create_should_not_send_email_notification_without_issue_updated
     issue = Issue.first
     user = User.first
-    journal = issue.init_journal(user, issue)
+    journal = issue.init_journal(user, "some notes")
 
     with_settings :notified_events => [] do
       assert journal.save
@@ -62,11 +62,10 @@ class JournalObserverTest < ActiveSupport::TestCase
     assert_equal 0, ActionMailer::Base.deliveries.size
   end
 
-  # context: issue_note_added notified_events
   def test_create_should_send_email_notification_with_issue_note_added
     issue = Issue.first
     user = User.first
-    journal = issue.init_journal(user, issue)
+    journal = issue.init_journal(user)
     journal.notes = 'This update has a note'
 
     with_settings :notified_events => %w(issue_note_added) do
@@ -78,7 +77,7 @@ class JournalObserverTest < ActiveSupport::TestCase
   def test_create_should_not_send_email_notification_without_issue_note_added
     issue = Issue.first
     user = User.first
-    journal = issue.init_journal(user, issue)
+    journal = issue.init_journal(user)
     journal.notes = 'This update has a note'
 
     with_settings :notified_events => [] do
@@ -87,11 +86,10 @@ class JournalObserverTest < ActiveSupport::TestCase
     assert_equal 0, ActionMailer::Base.deliveries.size
   end
 
-  # context: issue_status_updated notified_events
   def test_create_should_send_email_notification_with_issue_status_updated
     issue = Issue.first
     user = User.first
-    issue.init_journal(user, issue)
+    issue.init_journal(user)
     issue.status = IssueStatus.last
 
     with_settings :notified_events => %w(issue_status_updated) do
@@ -103,7 +101,7 @@ class JournalObserverTest < ActiveSupport::TestCase
   def test_create_should_not_send_email_notification_without_issue_status_updated
     issue = Issue.first
     user = User.first
-    issue.init_journal(user, issue)
+    issue.init_journal(user)
     issue.status = IssueStatus.last
 
     with_settings :notified_events => [] do
@@ -112,11 +110,48 @@ class JournalObserverTest < ActiveSupport::TestCase
     assert_equal 0, ActionMailer::Base.deliveries.size
   end
 
-  # context: issue_priority_updated notified_events
+  def test_create_without_status_update_should_not_send_email_notification_with_issue_status_updated
+    issue = Issue.first
+    user = User.first
+    issue.init_journal(user)
+    issue.subject = "No status update"
+
+    with_settings :notified_events => %w(issue_status_updated) do
+      assert issue.save
+    end
+    assert_equal 0, ActionMailer::Base.deliveries.size
+  end
+
+  def test_create_should_send_email_notification_with_issue_assignee_updated
+    issue = Issue.generate!(:assigned_to_id => 2)
+    ActionMailer::Base.deliveries.clear
+    user = User.first
+    issue.init_journal(user)
+    issue.assigned_to = User.find(3)
+
+    with_settings :notified_events => %w(issue_assigned_to_updated) do
+      assert issue.save
+    end
+    assert_equal 1, ActionMailer::Base.deliveries.size
+  end
+
+  def test_create_should_not_send_email_notification_without_issue_assignee_updated
+    issue = Issue.generate!(:assigned_to_id => 2)
+    ActionMailer::Base.deliveries.clear
+    user = User.first
+    issue.init_journal(user)
+    issue.assigned_to = User.find(3)
+
+    with_settings :notified_events => [] do
+      assert issue.save
+    end
+    assert_equal 0, ActionMailer::Base.deliveries.size
+  end
+
   def test_create_should_send_email_notification_with_issue_priority_updated
     issue = Issue.first
     user = User.first
-    issue.init_journal(user, issue)
+    issue.init_journal(user)
     issue.priority = IssuePriority.last
 
     with_settings :notified_events => %w(issue_priority_updated) do
@@ -128,7 +163,7 @@ class JournalObserverTest < ActiveSupport::TestCase
   def test_create_should_not_send_email_notification_without_issue_priority_updated
     issue = Issue.first
     user = User.first
-    issue.init_journal(user, issue)
+    issue.init_journal(user)
     issue.priority = IssuePriority.last
 
     with_settings :notified_events => [] do
diff --git a/test/unit/journal_test.rb b/test/unit/journal_test.rb
index 1f0c523..8c90ba1 100644
--- a/test/unit/journal_test.rb
+++ b/test/unit/journal_test.rb
@@ -19,8 +19,11 @@ require File.expand_path('../../test_helper', __FILE__)
 
 class JournalTest < ActiveSupport::TestCase
   fixtures :projects, :issues, :issue_statuses, :journals, :journal_details,
+           :issue_relations, :workflows,
            :users, :members, :member_roles, :roles, :enabled_modules,
-           :projects_trackers, :trackers
+           :groups_users,
+           :enumerations,
+           :projects_trackers, :trackers, :custom_fields
 
   def setup
     @journal = Journal.find 1
@@ -116,12 +119,12 @@ class JournalTest < ActiveSupport::TestCase
 
   def test_visible_scope_for_anonymous
     # Anonymous user should see issues of public projects only
-    journals = Journal.visible(User.anonymous).all
+    journals = Journal.visible(User.anonymous).to_a
     assert journals.any?
     assert_nil journals.detect {|journal| !journal.issue.project.is_public?}
     # Anonymous user should not see issues without permission
     Role.anonymous.remove_permission!(:view_issues)
-    journals = Journal.visible(User.anonymous).all
+    journals = Journal.visible(User.anonymous).to_a
     assert journals.empty?
   end
 
@@ -129,18 +132,18 @@ class JournalTest < ActiveSupport::TestCase
     user = User.find(9)
     assert user.projects.empty?
     # Non member user should see issues of public projects only
-    journals = Journal.visible(user).all
+    journals = Journal.visible(user).to_a
     assert journals.any?
     assert_nil journals.detect {|journal| !journal.issue.project.is_public?}
     # Non member user should not see issues without permission
     Role.non_member.remove_permission!(:view_issues)
     user.reload
-    journals = Journal.visible(user).all
+    journals = Journal.visible(user).to_a
     assert journals.empty?
     # User should see issues of projects for which user has view_issues permissions only
     Member.create!(:principal => user, :project_id => 1, :role_ids => [1])
     user.reload
-    journals = Journal.visible(user).all
+    journals = Journal.visible(user).to_a
     assert journals.any?
     assert_nil journals.detect {|journal| journal.issue.project_id != 1}
   end
@@ -149,7 +152,7 @@ class JournalTest < ActiveSupport::TestCase
     user = User.find(1)
     user.members.each(&:destroy)
     assert user.projects.empty?
-    journals = Journal.visible(user).all
+    journals = Journal.visible(user).to_a
     assert journals.any?
     # Admin should see issues on private projects that admin does not belong to
     assert journals.detect {|journal| !journal.issue.project.is_public?}
diff --git a/test/unit/lib/redmine/codeset_util_test.rb b/test/unit/lib/redmine/codeset_util_test.rb
index 496ab5f..0758ec4 100644
--- a/test/unit/lib/redmine/codeset_util_test.rb
+++ b/test/unit/lib/redmine/codeset_util_test.rb
@@ -21,14 +21,9 @@ class Redmine::CodesetUtilTest < ActiveSupport::TestCase
 
   def test_to_utf8_by_setting_from_latin1
     with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
-      s1 = "Texte encod\xc3\xa9"
-      s2 = "Texte encod\xe9"
-      s3 = s2.dup
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding("UTF-8")
-        s2.force_encoding("ASCII-8BIT")
-        s3.force_encoding("UTF-8")
-      end
+      s1 = "Texte encod\xc3\xa9".force_encoding("UTF-8")
+      s2 = "Texte encod\xe9".force_encoding("ASCII-8BIT")
+      s3 = s2.dup.force_encoding("UTF-8")
       assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
       assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
     end
@@ -36,14 +31,9 @@ class Redmine::CodesetUtilTest < ActiveSupport::TestCase
 
   def test_to_utf8_by_setting_from_euc_jp
     with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
-      s1 = "\xe3\x83\xac\xe3\x83\x83\xe3\x83\x89\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xb3"
-      s2 = "\xa5\xec\xa5\xc3\xa5\xc9\xa5\xde\xa5\xa4\xa5\xf3"
-      s3 = s2.dup
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding("UTF-8")
-        s2.force_encoding("ASCII-8BIT")
-        s3.force_encoding("UTF-8")
-      end
+      s1 = "\xe3\x83\xac\xe3\x83\x83\xe3\x83\x89\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xb3".force_encoding("UTF-8")
+      s2 = "\xa5\xec\xa5\xc3\xa5\xc9\xa5\xde\xa5\xa4\xa5\xf3".force_encoding("ASCII-8BIT")
+      s3 = s2.dup.force_encoding("UTF-8")
       assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
       assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
     end
@@ -51,14 +41,9 @@ class Redmine::CodesetUtilTest < ActiveSupport::TestCase
 
   def test_to_utf8_by_setting_should_be_converted_all_latin1
     with_settings :repositories_encodings => 'ISO-8859-1' do
-      s1 = "\xc3\x82\xc2\x80"
-      s2 = "\xC2\x80"
-      s3 = s2.dup
-      if s1.respond_to?(:force_encoding)
-        s1.force_encoding("UTF-8")
-        s2.force_encoding("ASCII-8BIT")
-        s3.force_encoding("UTF-8")
-      end
+      s1 = "\xc3\x82\xc2\x80".force_encoding("UTF-8")
+      s2 = "\xC2\x80".force_encoding("ASCII-8BIT")
+      s3 = s2.dup.force_encoding("UTF-8")
       assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
       assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
     end
@@ -70,45 +55,33 @@ class Redmine::CodesetUtilTest < ActiveSupport::TestCase
   end
 
   def test_to_utf8_by_setting_returns_ascii_as_utf8
-    s1 = "ASCII"
-    s2 = s1.dup
-    if s1.respond_to?(:force_encoding)
-      s1.force_encoding("UTF-8")
-      s2.force_encoding("ISO-8859-1")
-    end
+    s1 = "ASCII".force_encoding("UTF-8")
+    s2 = s1.dup.force_encoding("ISO-8859-1")
     str1 = Redmine::CodesetUtil.to_utf8_by_setting(s1)
     str2 = Redmine::CodesetUtil.to_utf8_by_setting(s2)
     assert_equal s1, str1
     assert_equal s1, str2
-    if s1.respond_to?(:force_encoding)
-      assert_equal "UTF-8", str1.encoding.to_s
-      assert_equal "UTF-8", str2.encoding.to_s
-    end
+    assert_equal "UTF-8", str1.encoding.to_s
+    assert_equal "UTF-8", str2.encoding.to_s
   end
 
   def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped
     with_settings :repositories_encodings => '' do
       # s1 = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
-      s1 = "Texte encod\xe9 en ISO-8859-1."
-      s1.force_encoding("ASCII-8BIT") if s1.respond_to?(:force_encoding)
+      s1 = "Texte encod\xe9 en ISO-8859-1.".force_encoding("ASCII-8BIT")
       str = Redmine::CodesetUtil.to_utf8_by_setting(s1)
-      if str.respond_to?(:force_encoding)
-        assert str.valid_encoding?
-        assert_equal "UTF-8", str.encoding.to_s
-      end
+      assert str.valid_encoding?
+      assert_equal "UTF-8", str.encoding.to_s
       assert_equal "Texte encod? en ISO-8859-1.", str
     end
   end
 
   def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped_ja_jis
     with_settings :repositories_encodings => 'ISO-2022-JP' do
-      s1 = "test\xb5\xfetest\xb5\xfe"
-      s1.force_encoding("ASCII-8BIT") if s1.respond_to?(:force_encoding)
+      s1 = "test\xb5\xfetest\xb5\xfe".force_encoding("ASCII-8BIT")
       str = Redmine::CodesetUtil.to_utf8_by_setting(s1)
-      if str.respond_to?(:force_encoding)
-        assert str.valid_encoding?
-        assert_equal "UTF-8", str.encoding.to_s
-      end
+      assert str.valid_encoding?
+      assert_equal "UTF-8", str.encoding.to_s
       assert_equal "test??test??", str
     end
   end
diff --git a/test/unit/lib/redmine/export/pdf_test.rb b/test/unit/lib/redmine/export/pdf_test.rb
index a0821d6..8af6726 100644
--- a/test/unit/lib/redmine/export/pdf_test.rb
+++ b/test/unit/lib/redmine/export/pdf_test.rb
@@ -27,11 +27,10 @@ class PdfTest < ActiveSupport::TestCase
   end
 
   def test_rdm_pdf_iconv_cannot_convert_ja_cp932
-    encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
     utf8_txt_1  = "\xe7\x8b\x80\xe6\x85\x8b"
     utf8_txt_2  = "\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
     utf8_txt_3  = "\xe7\x8b\x80\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
-    if utf8_txt_1.respond_to?(:force_encoding)
+    ["CP932", "SJIS"].each do |encoding|
       txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
       txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
       txt_3 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
@@ -41,88 +40,65 @@ class PdfTest < ActiveSupport::TestCase
       assert_equal "ASCII-8BIT", txt_1.encoding.to_s
       assert_equal "ASCII-8BIT", txt_2.encoding.to_s
       assert_equal "ASCII-8BIT", txt_3.encoding.to_s
-    elsif RUBY_PLATFORM == 'java'
-      assert_equal "??",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
-      assert_equal "???",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
-      assert_equal "????",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
-    else
-      assert_equal "???\x91\xd4",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
-      assert_equal "???\x91\xd4???",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
-      assert_equal "??????\x91\xd4???",
-                   Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
     end
   end
 
   def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_en
-    str1 = "Texte encod\xe9 en ISO-8859-1"
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
+    str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8")
+    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
     txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, 'UTF-8')
     txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, 'UTF-8')
-    if txt_1.respond_to?(:force_encoding)
-      assert_equal "ASCII-8BIT", txt_1.encoding.to_s
-      assert_equal "ASCII-8BIT", txt_2.encoding.to_s
-    end
+    assert_equal "ASCII-8BIT", txt_1.encoding.to_s
+    assert_equal "ASCII-8BIT", txt_2.encoding.to_s
     assert_equal "Texte encod? en ISO-8859-1", txt_1
     assert_equal "?a?b?c?d?e test", txt_2
   end
 
   def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja
-    str1 = "Texte encod\xe9 en ISO-8859-1"
-    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
-    str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
+    str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8")
+    str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
     encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
     txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, encoding)
     txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, encoding)
-    if txt_1.respond_to?(:force_encoding)
-      assert_equal "ASCII-8BIT", txt_1.encoding.to_s
-      assert_equal "ASCII-8BIT", txt_2.encoding.to_s
-    end
+    assert_equal "ASCII-8BIT", txt_1.encoding.to_s
+    assert_equal "ASCII-8BIT", txt_2.encoding.to_s
     assert_equal "Texte encod? en ISO-8859-1", txt_1
     assert_equal "?a?b?c?d?e test", txt_2
   end
 
   def test_attach
-    set_fixtures_attachments_directory
+    ["CP932", "SJIS"].each do |encoding|
+      set_fixtures_attachments_directory
 
-    str2 = "\x83e\x83X\x83g"
-    str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
-    encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
+      str2 = "\x83e\x83X\x83g".force_encoding("ASCII-8BIT")
 
-    a1 = Attachment.find(17)
-    a2 = Attachment.find(19)
+      a1 = Attachment.find(17)
+      a2 = Attachment.find(19)
+      User.current = User.find(1)
+      assert a1.readable?
+      assert a1.visible?
+      assert a2.readable?
+      assert a2.visible?
 
-    User.current = User.find(1)
-    assert a1.readable?
-    assert a1.visible?
-    assert a2.readable?
-    assert a2.visible?
+      aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
+      assert_not_nil aa1
+      assert_equal 17, aa1.id
 
-    aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
-    assert_not_nil aa1
-    assert_equal 17, aa1.id
-    aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
-    assert_not_nil aa2
-    assert_equal 19, aa2.id
+      aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
+      assert_not_nil aa2
+      assert_equal 19, aa2.id
 
-    User.current = nil
-    assert a1.readable?
-    assert (! a1.visible?)
-    assert a2.readable?
-    assert (! a2.visible?)
+      User.current = nil
+      assert a1.readable?
+      assert (! a1.visible?)
+      assert a2.readable?
+      assert (! a2.visible?)
+      aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
+      assert_equal nil, aa1
+      aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
+      assert_equal nil, aa2
 
-    aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
-    assert_equal nil, aa1
-    aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
-    assert_equal nil, aa2
-
-    set_tmp_attachments_directory
+      set_tmp_attachments_directory
+    end
   end
 end
diff --git a/test/unit/lib/redmine/hook_test.rb b/test/unit/lib/redmine/hook_test.rb
index 1352d25..af9ca9d 100644
--- a/test/unit/lib/redmine/hook_test.rb
+++ b/test/unit/lib/redmine/hook_test.rb
@@ -66,6 +66,7 @@ class Redmine::Hook::ManagerTest < ActionView::TestCase
 
   def setup
     @hook_module = Redmine::Hook
+    @hook_module.clear_listeners
   end
 
   def teardown
diff --git a/test/unit/lib/redmine/i18n_test.rb b/test/unit/lib/redmine/i18n_test.rb
index fc1fdf3..58eb676 100644
--- a/test/unit/lib/redmine/i18n_test.rb
+++ b/test/unit/lib/redmine/i18n_test.rb
@@ -32,47 +32,50 @@ class Redmine::I18nTest < ActiveSupport::TestCase
   def test_date_format_default
     set_language_if_valid 'en'
     today = Date.today
-    Setting.date_format = ''
-    assert_equal I18n.l(today), format_date(today)
+    with_settings :date_format => '' do
+      assert_equal I18n.l(today), format_date(today)
+    end
   end
 
   def test_date_format
     set_language_if_valid 'en'
     today = Date.today
-    Setting.date_format = '%d %m %Y'
-    assert_equal today.strftime('%d %m %Y'), format_date(today)
+    with_settings :date_format => '%d %m %Y' do
+      assert_equal today.strftime('%d %m %Y'), format_date(today)
+    end
   end
 
   def test_date_format_default_with_user_locale
     set_language_if_valid 'es'
     today = now = Time.parse('2011-02-20 14:00:00')
-    Setting.date_format = '%d %B %Y'
-    User.current.language = 'fr'
-    s1 = "20 f\xc3\xa9vrier 2011"
-    s1.force_encoding("UTF-8") if s1.respond_to?(:force_encoding)
-    assert_equal s1, format_date(today)
-    User.current.language = nil
-    assert_equal '20 Febrero 2011', format_date(today)
+    with_settings :date_format => '%d %B %Y' do
+      User.current.language = 'fr'
+      s1 = "20 f\xc3\xa9vrier 2011".force_encoding("UTF-8")
+      assert_equal s1, format_date(today)
+      User.current.language = nil
+      assert_equal '20 Febrero 2011', format_date(today)
+    end
   end
 
   def test_date_and_time_for_each_language
-    Setting.date_format = ''
-    valid_languages.each do |lang|
-      set_language_if_valid lang
-      assert_nothing_raised "#{lang} failure" do
-        format_date(Date.today)
-        format_time(Time.now)
-        format_time(Time.now, false)
-        assert_not_equal 'default', ::I18n.l(Date.today, :format => :default),
-                         "date.formats.default missing in #{lang}"
-        assert_not_equal 'time',    ::I18n.l(Time.now, :format => :time),
-                         "time.formats.time missing in #{lang}"
+    with_settings :date_format => '' do
+      valid_languages.each do |lang|
+        set_language_if_valid lang
+        assert_nothing_raised "#{lang} failure" do
+          format_date(Date.today)
+          format_time(Time.now)
+          format_time(Time.now, false)
+          assert_not_equal 'default', ::I18n.l(Date.today, :format => :default),
+                           "date.formats.default missing in #{lang}"
+          assert_not_equal 'time',    ::I18n.l(Time.now, :format => :time),
+                           "time.formats.time missing in #{lang}"
+        end
+        assert l('date.day_names').is_a?(Array)
+        assert_equal 7, l('date.day_names').size
+  
+        assert l('date.month_names').is_a?(Array)
+        assert_equal 13, l('date.month_names').size
       end
-      assert l('date.day_names').is_a?(Array)
-      assert_equal 7, l('date.day_names').size
-
-      assert l('date.month_names').is_a?(Array)
-      assert_equal 13, l('date.month_names').size
     end
   end
 
@@ -134,10 +137,10 @@ class Redmine::I18nTest < ActiveSupport::TestCase
   def test_utc_time_format
     set_language_if_valid 'en'
     now = Time.now
-    Setting.date_format = '%d %m %Y'
-    Setting.time_format = '%H %M'
-    assert_equal now.strftime('%d %m %Y %H %M'), format_time(now.utc)
-    assert_equal now.strftime('%H %M'), format_time(now.utc, false)
+    with_settings :date_format => '%d %m %Y', :time_format => '%H %M' do
+      assert_equal now.strftime('%d %m %Y %H %M'), format_time(now.utc)
+      assert_equal now.strftime('%H %M'), format_time(now.utc, false)
+    end
   end
 
   def test_number_to_human_size_for_each_language
@@ -175,8 +178,7 @@ class Redmine::I18nTest < ActiveSupport::TestCase
     set_language_if_valid 'bs'
     assert_equal "KM -1000,20", number_to_currency(-1000.2)
     set_language_if_valid 'de'
-    euro_sign = "\xe2\x82\xac"
-    euro_sign.force_encoding('UTF-8') if euro_sign.respond_to?(:force_encoding)
+    euro_sign = "\xe2\x82\xac".force_encoding('UTF-8')
     assert_equal "-1000,20 #{euro_sign}", number_to_currency(-1000.2)
   end
 
@@ -193,8 +195,7 @@ class Redmine::I18nTest < ActiveSupport::TestCase
     assert_nil options.detect {|option| option.size != 2}
     assert_nil options.detect {|option| !option.first.is_a?(String) || !option.last.is_a?(String)}
     assert_include ["English", "en"], options
-    ja = "Japanese (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
+    ja = "Japanese (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)".force_encoding('UTF-8')
     assert_include [ja, "ja"], options
   end
 
@@ -233,30 +234,21 @@ class Redmine::I18nTest < ActiveSupport::TestCase
 
   def test_utf8
     set_language_if_valid 'ja'
-    str_ja_yes  = "\xe3\x81\xaf\xe3\x81\x84"
+    str_ja_yes  = "\xe3\x81\xaf\xe3\x81\x84".force_encoding('UTF-8')
     i18n_ja_yes = l(:general_text_Yes)
-    if str_ja_yes.respond_to?(:force_encoding)
-      str_ja_yes.force_encoding('UTF-8')
-      assert_equal "UTF-8", i18n_ja_yes.encoding.to_s
-    end
     assert_equal str_ja_yes, i18n_ja_yes
+    assert_equal "UTF-8", i18n_ja_yes.encoding.to_s
   end
 
   def test_traditional_chinese_locale
     set_language_if_valid 'zh-TW'
-    str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
-    if str_tw.respond_to?(:force_encoding)
-      str_tw.force_encoding('UTF-8')
-    end
+    str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)".force_encoding('UTF-8')
     assert_equal str_tw, l(:general_lang_name)
   end
 
   def test_french_locale
     set_language_if_valid 'fr'
-    str_fr = "Fran\xc3\xa7ais"
-    if str_fr.respond_to?(:force_encoding)
-      str_fr.force_encoding('UTF-8')
-    end
+    str_fr = "Fran\xc3\xa7ais".force_encoding('UTF-8')
     assert_equal str_fr, l(:general_lang_name)
   end
 end
diff --git a/test/unit/lib/redmine/notifiable_test.rb b/test/unit/lib/redmine/notifiable_test.rb
index f1d9149..2e41326 100644
--- a/test/unit/lib/redmine/notifiable_test.rb
+++ b/test/unit/lib/redmine/notifiable_test.rb
@@ -22,9 +22,7 @@ class Redmine::NotifiableTest < ActiveSupport::TestCase
   end
 
   def test_all
-    assert_equal 12, Redmine::Notifiable.all.length
-
-    %w(issue_added issue_updated issue_note_added issue_status_updated issue_priority_updated news_added news_comment_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable|
+    %w(issue_added issue_updated issue_note_added issue_status_updated issue_assigned_to_updated issue_priority_updated news_added news_comment_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable|
       assert Redmine::Notifiable.all.collect(&:name).include?(notifiable), "missing #{notifiable}"
     end
   end
diff --git a/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb
index a4699ef..272b7ba 100644
--- a/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb
+++ b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb
@@ -16,210 +16,203 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class BazaarAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
-    REPOSITORY_PATH.gsub!(/\/+/, '/')
-
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        @adapter = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                File.join(REPOSITORY_PATH, "trunk")
-                                )
-      end
 
-      def test_scm_version
-        to_test = { "Bazaar (bzr) 2.1.2\n"             => [2,1,2],
-                    "2.1.1\n1.7\n1.8"                  => [2,1,1],
-                    "2.0.1\r\n1.8.1\r\n1.9.1"          => [2,0,1]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
-      end
+class BazaarAdapterTest < ActiveSupport::TestCase
+  REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
+  REPOSITORY_PATH.gsub!(/\/+/, '/')
 
-      def test_cat
-        cat = @adapter.cat('directory/document.txt')
-        assert cat =~ /Write the contents of a file as of a given revision to standard output/
-      end
+  if File.directory?(REPOSITORY_PATH)
+    def setup
+      @adapter = Redmine::Scm::Adapters::BazaarAdapter.new(
+                              File.join(REPOSITORY_PATH, "trunk")
+                              )
+    end
 
-      def test_cat_path_invalid
-        assert_nil @adapter.cat('invalid')
+    def test_scm_version
+      to_test = { "Bazaar (bzr) 2.1.2\n"             => [2,1,2],
+                  "2.1.1\n1.7\n1.8"                  => [2,1,1],
+                  "2.0.1\r\n1.8.1\r\n1.9.1"          => [2,0,1]}
+      to_test.each do |s, v|
+        test_scm_version_for(s, v)
       end
+    end
 
-      def test_cat_revision_invalid
-        assert_nil @adapter.cat('doc-mkdir.txt', '12345678')
-      end
+    def test_cat
+      cat = @adapter.cat('directory/document.txt')
+      assert cat =~ /Write the contents of a file as of a given revision to standard output/
+    end
 
-      def test_diff
-        diff1 = @adapter.diff('doc-mkdir.txt', 3, 2)
-        assert_equal 21, diff1.size
-        buf =  diff1[14].gsub(/\r\n|\r|\n/, "")
-        assert_equal "-Display more information.", buf
-      end
+    def test_cat_path_invalid
+      assert_nil @adapter.cat('invalid')
+    end
 
-      def test_diff_path_invalid
-        assert_equal [], @adapter.diff('invalid', 1)
-      end
+    def test_cat_revision_invalid
+      assert_nil @adapter.cat('doc-mkdir.txt', '12345678')
+    end
 
-      def test_diff_revision_invalid
-        assert_equal [], @adapter.diff(nil, 12345678)
-        assert_equal [], @adapter.diff(nil, 12345678, 87654321)
-      end
+    def test_diff
+      diff1 = @adapter.diff('doc-mkdir.txt', 3, 2)
+      assert_equal 21, diff1.size
+      buf =  diff1[14].gsub(/\r\n|\r|\n/, "")
+      assert_equal "-Display more information.", buf
+    end
 
-      def test_annotate
-        annotate = @adapter.annotate('doc-mkdir.txt')
-        assert_equal 17, annotate.lines.size
-        assert_equal '1', annotate.revisions[0].identifier
-        assert_equal 'jsmith@', annotate.revisions[0].author
-        assert_equal 'mkdir', annotate.lines[0]
-      end
+    def test_diff_path_invalid
+      assert_equal [], @adapter.diff('invalid', 1)
+    end
 
-      def test_annotate_path_invalid
-        assert_nil @adapter.annotate('invalid')
-      end
+    def test_diff_revision_invalid
+      assert_equal [], @adapter.diff(nil, 12345678)
+      assert_equal [], @adapter.diff(nil, 12345678, 87654321)
+    end
 
-      def test_annotate_revision_invalid
-        assert_nil @adapter.annotate('doc-mkdir.txt', '12345678')
-      end
+    def test_annotate
+      annotate = @adapter.annotate('doc-mkdir.txt')
+      assert_equal 17, annotate.lines.size
+      assert_equal '1', annotate.revisions[0].identifier
+      assert_equal 'jsmith@', annotate.revisions[0].author
+      assert_equal 'mkdir', annotate.lines[0]
+    end
 
-      def test_branch_conf_path
-        p = "c:\\test\\test\\"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "c:\\test\\test\\.bzr"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "c:\\test\\test\\.bzr\\"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "c:\\test\\test"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-        p = "\\\\server\\test\\test\\"
-        bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
-        assert_equal File.join("\\\\server\\test\\test", ".bzr", "branch", "branch.conf"), bcp
-      end
+    def test_annotate_path_invalid
+      assert_nil @adapter.annotate('invalid')
+    end
 
-      def test_append_revisions_only_true
-        assert_equal true, @adapter.append_revisions_only
-      end
+    def test_annotate_revision_invalid
+      assert_nil @adapter.annotate('doc-mkdir.txt', '12345678')
+    end
 
-      def test_append_revisions_only_false
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                File.join(REPOSITORY_PATH, "empty-branch")
-                                )
-        assert_equal false, adpt.append_revisions_only
-      end
+    def test_branch_conf_path
+      p = "c:\\test\\test\\"
+      bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
+      assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
+      p = "c:\\test\\test\\.bzr"
+      bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
+      assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
+      p = "c:\\test\\test\\.bzr\\"
+      bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
+      assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
+      p = "c:\\test\\test"
+      bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
+      assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
+      p = "\\\\server\\test\\test\\"
+      bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
+      assert_equal File.join("\\\\server\\test\\test", ".bzr", "branch", "branch.conf"), bcp
+    end
 
-      def test_append_revisions_only_shared_repo
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                REPOSITORY_PATH
-                                )
-        assert_equal false, adpt.append_revisions_only
-      end
+    def test_append_revisions_only_true
+      assert_equal true, @adapter.append_revisions_only
+    end
 
-      def test_info_not_nil
-        assert_not_nil @adapter.info
-      end
+    def test_append_revisions_only_false
+      adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
+                              File.join(REPOSITORY_PATH, "empty-branch")
+                              )
+      assert_equal false, adpt.append_revisions_only
+    end
 
-      def test_info_nil
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                  "/invalid/invalid/"
-                  )
-        assert_nil adpt.info
-      end
+    def test_append_revisions_only_shared_repo
+      adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
+                              REPOSITORY_PATH
+                              )
+      assert_equal false, adpt.append_revisions_only
+    end
 
-      def test_info
-        info = @adapter.info
-        assert_equal 4, info.lastrev.identifier.to_i
-      end
+    def test_info_not_nil
+      assert_not_nil @adapter.info
+    end
 
-      def test_info_emtpy
-        adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
-                                File.join(REPOSITORY_PATH, "empty-branch")
-                                )
-        assert_equal 0, adpt.info.lastrev.identifier.to_i
-      end
+    def test_info_nil
+      adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
+                "/invalid/invalid/"
+                )
+      assert_nil adpt.info
+    end
 
-      def test_entries_path_invalid
-        assert_equal [], @adapter.entries('invalid')
-      end
+    def test_info
+      info = @adapter.info
+      assert_equal 4, info.lastrev.identifier.to_i
+    end
 
-      def test_entries_revision_invalid
-        assert_nil @adapter.entries(nil, 12345678)
-      end
+    def test_info_emtpy
+      adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
+                              File.join(REPOSITORY_PATH, "empty-branch")
+                              )
+      assert_equal 0, adpt.info.lastrev.identifier.to_i
+    end
 
-      def test_revisions
-        revisions = @adapter.revisions(nil, 4, 2)
-        assert_equal 3, revisions.size
-        assert_equal 2, revisions[2].identifier
-        assert_equal 'jsmith at foo.bar-20071203175224-v0eog5d5wrgdrshg', revisions[2].scmid
-        assert_equal 4, revisions[0].identifier
-        assert_equal 'jsmith at foo.bar-20071203175422-t40bf8li5zz0c4cg', revisions[0].scmid
-        assert_equal 2, revisions[0].paths.size
-        assert_equal 'D', revisions[0].paths[0][:action]
-        assert_equal '/doc-deleted.txt', revisions[0].paths[0][:path]
-        assert_equal 'docdeleted.txt-20071203175320-iwwj561ojuubs3gt-1', revisions[0].paths[0][:revision]
-        assert_equal 'M', revisions[0].paths[1][:action]
-        assert_equal '/directory/doc-ls.txt', revisions[0].paths[1][:path]
-        assert_equal 'docls.txt-20071203175005-a3hyc3mn0shl7cgu-1', revisions[0].paths[1][:revision]
-      end
+    def test_entries_path_invalid
+      assert_equal [], @adapter.entries('invalid')
+    end
 
-      def test_revisions_path_invalid
-        assert_nil @adapter.revisions('invalid')
-      end
+    def test_entries_revision_invalid
+      assert_nil @adapter.entries(nil, 12345678)
+    end
 
-      def test_revisions_revision_invalid
-        assert_nil @adapter.revisions(nil, 12345678)
-        assert_nil @adapter.revisions(nil, 12345678, 87654321)
-      end
+    def test_revisions
+      revisions = @adapter.revisions(nil, 4, 2)
+      assert_equal 3, revisions.size
+      assert_equal 2, revisions[2].identifier
+      assert_equal 'jsmith at foo.bar-20071203175224-v0eog5d5wrgdrshg', revisions[2].scmid
+      assert_equal 4, revisions[0].identifier
+      assert_equal 'jsmith at foo.bar-20071203175422-t40bf8li5zz0c4cg', revisions[0].scmid
+      assert_equal 2, revisions[0].paths.size
+      assert_equal 'D', revisions[0].paths[0][:action]
+      assert_equal '/doc-deleted.txt', revisions[0].paths[0][:path]
+      assert_equal 'docdeleted.txt-20071203175320-iwwj561ojuubs3gt-1', revisions[0].paths[0][:revision]
+      assert_equal 'M', revisions[0].paths[1][:action]
+      assert_equal '/directory/doc-ls.txt', revisions[0].paths[1][:path]
+      assert_equal 'docls.txt-20071203175005-a3hyc3mn0shl7cgu-1', revisions[0].paths[1][:revision]
+    end
 
-      def test_entry
-        entry = @adapter.entry()
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        entry = @adapter.entry('')
-        assert_equal "", entry.path
+    def test_revisions_path_invalid
+      assert_nil @adapter.revisions('invalid')
+    end
+
+    def test_revisions_revision_invalid
+      assert_nil @adapter.revisions(nil, 12345678)
+      assert_nil @adapter.revisions(nil, 12345678, 87654321)
+    end
+
+    def test_entry
+      entry = @adapter.entry()
+      assert_equal "", entry.path
+      assert_equal "dir", entry.kind
+      entry = @adapter.entry('')
+      assert_equal "", entry.path
+      assert_equal "dir", entry.kind
+      assert_nil @adapter.entry('invalid')
+      assert_nil @adapter.entry('/invalid')
+      assert_nil @adapter.entry('/invalid/')
+      assert_nil @adapter.entry('invalid/invalid')
+      assert_nil @adapter.entry('invalid/invalid/')
+      assert_nil @adapter.entry('/invalid/invalid')
+      assert_nil @adapter.entry('/invalid/invalid/')
+      ["doc-ls.txt", "/doc-ls.txt"].each do |path|
+        entry = @adapter.entry(path, 2)
+        assert_equal "doc-ls.txt", entry.path
+        assert_equal "file", entry.kind
+      end
+      ["directory", "/directory", "/directory/"].each do |path|
+        entry = @adapter.entry(path, 2)
+        assert_equal "directory", entry.path
         assert_equal "dir", entry.kind
-        assert_nil @adapter.entry('invalid')
-        assert_nil @adapter.entry('/invalid')
-        assert_nil @adapter.entry('/invalid/')
-        assert_nil @adapter.entry('invalid/invalid')
-        assert_nil @adapter.entry('invalid/invalid/')
-        assert_nil @adapter.entry('/invalid/invalid')
-        assert_nil @adapter.entry('/invalid/invalid/')
-        ["doc-ls.txt", "/doc-ls.txt"].each do |path|
-          entry = @adapter.entry(path, 2)
-          assert_equal "doc-ls.txt", entry.path
-          assert_equal "file", entry.kind
-        end
-        ["directory", "/directory", "/directory/"].each do |path|
-          entry = @adapter.entry(path, 2)
-          assert_equal "directory", entry.path
-          assert_equal "dir", entry.kind
-        end
-        ["directory/document.txt", "/directory/document.txt"].each do |path|
-          entry = @adapter.entry(path, 2)
-          assert_equal "directory/document.txt", entry.path
-          assert_equal "file", entry.kind
-        end
       end
+      ["directory/document.txt", "/directory/document.txt"].each do |path|
+        entry = @adapter.entry(path, 2)
+        assert_equal "directory/document.txt", entry.path
+        assert_equal "file", entry.kind
+      end
+    end
 
-      private
+    private
 
-      def test_scm_version_for(scm_command_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
-        assert_equal version, @adapter.class.scm_command_version
-      end
-    else
-      puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
+    def test_scm_version_for(scm_command_version, version)
+      @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
+      assert_equal version, @adapter.class.scm_command_version
     end
-  end
-rescue LoadError
-  class BazaarMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
+  else
+    puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!"
+    def test_fake; assert true end
   end
 end
diff --git a/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb
index cf5ab79..504a3ad 100644
--- a/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb
+++ b/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb
@@ -16,100 +16,91 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
 
-  class CvsAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s
-    REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
-    MODULE_NAME = 'test'
+class CvsAdapterTest < ActiveSupport::TestCase
+  REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s
+  REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
+  MODULE_NAME = 'test'
 
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        @adapter = Redmine::Scm::Adapters::CvsAdapter.new(MODULE_NAME, REPOSITORY_PATH)
-      end
+  if File.directory?(REPOSITORY_PATH)
+    def setup
+      @adapter = Redmine::Scm::Adapters::CvsAdapter.new(MODULE_NAME, REPOSITORY_PATH)
+    end
 
-      def test_scm_version
-        to_test = { "\nConcurrent Versions System (CVS) 1.12.13 (client/server)\n"  => [1,12,13],
-                    "\r\n1.12.12\r\n1.12.11"                   => [1,12,12],
-                    "1.12.11\r\n1.12.10\r\n"                   => [1,12,11]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
+    def test_scm_version
+      to_test = { "\nConcurrent Versions System (CVS) 1.12.13 (client/server)\n"  => [1,12,13],
+                  "\r\n1.12.12\r\n1.12.11"                   => [1,12,12],
+                  "1.12.11\r\n1.12.10\r\n"                   => [1,12,11]}
+      to_test.each do |s, v|
+        test_scm_version_for(s, v)
       end
+    end
 
-      def test_revisions_all
-        cnt = 0
-        @adapter.revisions('', nil, nil, :log_encoding => 'UTF-8') do |revision|
-          cnt += 1
-        end
-        assert_equal 16, cnt
+    def test_revisions_all
+      cnt = 0
+      @adapter.revisions('', nil, nil, :log_encoding => 'UTF-8') do |revision|
+        cnt += 1
       end
+      assert_equal 16, cnt
+    end
 
-      def test_revisions_from_rev3
-        rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
-        cnt = 0
-        @adapter.revisions('', rev3_committed_on, nil, :log_encoding => 'UTF-8') do |revision|
-          cnt += 1
-        end
-        assert_equal 4, cnt
+    def test_revisions_from_rev3
+      rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
+      cnt = 0
+      @adapter.revisions('', rev3_committed_on, nil, :log_encoding => 'UTF-8') do |revision|
+        cnt += 1
       end
+      assert_equal 4, cnt
+    end
 
-      def test_entries_rev3
-        rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
-        entries = @adapter.entries('sources', rev3_committed_on)
-        assert_equal 2, entries.size
-        assert_equal entries[0].name, "watchers_controller.rb"
-        assert_equal entries[0].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22)
-      end
+    def test_entries_rev3
+      rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
+      entries = @adapter.entries('sources', rev3_committed_on)
+      assert_equal 2, entries.size
+      assert_equal entries[0].name, "watchers_controller.rb"
+      assert_equal entries[0].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22)
+    end
 
-      def test_path_encoding_default_utf8
-        adpt1 = Redmine::Scm::Adapters::CvsAdapter.new(
-                                  MODULE_NAME,
-                                  REPOSITORY_PATH
-                                )
-        assert_equal "UTF-8", adpt1.path_encoding
-        adpt2 = Redmine::Scm::Adapters::CvsAdapter.new(
-                                  MODULE_NAME,
-                                  REPOSITORY_PATH,
-                                  nil,
-                                  nil,
-                                  ""
-                                )
-        assert_equal "UTF-8", adpt2.path_encoding
-      end
+    def test_path_encoding_default_utf8
+      adpt1 = Redmine::Scm::Adapters::CvsAdapter.new(
+                                MODULE_NAME,
+                                REPOSITORY_PATH
+                              )
+      assert_equal "UTF-8", adpt1.path_encoding
+      adpt2 = Redmine::Scm::Adapters::CvsAdapter.new(
+                                MODULE_NAME,
+                                REPOSITORY_PATH,
+                                nil,
+                                nil,
+                                ""
+                              )
+      assert_equal "UTF-8", adpt2.path_encoding
+    end
 
-      def test_root_url_path
-        to_test = {
-          ':pserver:cvs_user:cvs_password at 123.456.789.123:9876/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password at 123.456.789.123/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password at cvs_server:/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password at cvs_server:9876/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password at cvs_server/repo' => '/repo',
-          ':pserver:cvs_user:cvs_password at cvs_server/path/repo' => '/path/repo',
-          ':ext:cvsservername:/path' => '/path'
-        }
+    def test_root_url_path
+      to_test = {
+        ':pserver:cvs_user:cvs_password at 123.456.789.123:9876/repo' => '/repo',
+        ':pserver:cvs_user:cvs_password at 123.456.789.123/repo' => '/repo',
+        ':pserver:cvs_user:cvs_password at cvs_server:/repo' => '/repo',
+        ':pserver:cvs_user:cvs_password at cvs_server:9876/repo' => '/repo',
+        ':pserver:cvs_user:cvs_password at cvs_server/repo' => '/repo',
+        ':pserver:cvs_user:cvs_password at cvs_server/path/repo' => '/path/repo',
+        ':ext:cvsservername:/path' => '/path'
+      }
 
-        to_test.each do |string, expected|
-          assert_equal expected, Redmine::Scm::Adapters::CvsAdapter.new('foo', string).send(:root_url_path), "#{string} failed"
-        end
+      to_test.each do |string, expected|
+        assert_equal expected, Redmine::Scm::Adapters::CvsAdapter.new('foo', string).send(:root_url_path), "#{string} failed"
       end
+    end
 
-      private
+    private
 
-      def test_scm_version_for(scm_command_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
-        assert_equal version, @adapter.class.scm_command_version
-      end
-    else
-      puts "Cvs test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
+    def test_scm_version_for(scm_command_version, version)
+      @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
+      assert_equal version, @adapter.class.scm_command_version
     end
-  end
-
-rescue LoadError
-  class CvsMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
+  else
+    puts "Cvs test repository NOT FOUND. Skipping unit tests !!!"
+    def test_fake; assert true end
   end
 end
-
diff --git a/test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb
index b6f8775..e28c849 100644
--- a/test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb
+++ b/test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb
@@ -16,54 +16,45 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
 
-  class DarcsAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s
+class DarcsAdapterTest < ActiveSupport::TestCase
+  REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s
 
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        @adapter = Redmine::Scm::Adapters::DarcsAdapter.new(REPOSITORY_PATH)
-      end
-
-      def test_darcsversion
-        to_test = { "1.0.9 (release)\n"  => [1,0,9] ,
-                    "2.2.0 (release)\n"  => [2,2,0] }
-        to_test.each do |s, v|
-          test_darcsversion_for(s, v)
-        end
-      end
+  if File.directory?(REPOSITORY_PATH)
+    def setup
+      @adapter = Redmine::Scm::Adapters::DarcsAdapter.new(REPOSITORY_PATH)
+    end
 
-      def test_revisions
-        id1 = '20080308225258-98289-761f654d669045eabee90b91b53a21ce5593cadf.gz'
-        revs = @adapter.revisions('', nil, nil, {:with_path => true})
-        assert_equal 6, revs.size
-        assert_equal id1, revs[5].scmid
-        paths = revs[5].paths
-        assert_equal 5, paths.size
-        assert_equal 'A', paths[0][:action]
-        assert_equal '/README', paths[0][:path]
-        assert_equal 'A', paths[1][:action]
-        assert_equal '/images', paths[1][:path]
+    def test_darcsversion
+      to_test = { "1.0.9 (release)\n"  => [1,0,9] ,
+                  "2.2.0 (release)\n"  => [2,2,0] }
+      to_test.each do |s, v|
+        test_darcsversion_for(s, v)
       end
+    end
 
-      private
+    def test_revisions
+      id1 = '20080308225258-98289-761f654d669045eabee90b91b53a21ce5593cadf.gz'
+      revs = @adapter.revisions('', nil, nil, {:with_path => true})
+      assert_equal 6, revs.size
+      assert_equal id1, revs[5].scmid
+      paths = revs[5].paths
+      assert_equal 5, paths.size
+      assert_equal 'A', paths[0][:action]
+      assert_equal '/README', paths[0][:path]
+      assert_equal 'A', paths[1][:action]
+      assert_equal '/images', paths[1][:path]
+    end
 
-      def test_darcsversion_for(darcsversion, version)
-        @adapter.class.expects(:darcs_binary_version_from_command_line).returns(darcsversion)
-        assert_equal version, @adapter.class.darcs_binary_version
-      end
+    private
 
-    else
-      puts "Darcs test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
+    def test_darcsversion_for(darcsversion, version)
+      @adapter.class.expects(:darcs_binary_version_from_command_line).returns(darcsversion)
+      assert_equal version, @adapter.class.darcs_binary_version
     end
-  end
 
-rescue LoadError
-  class DarcsMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
+  else
+    puts "Darcs test repository NOT FOUND. Skipping unit tests !!!"
+    def test_fake; assert true end
   end
 end
-
diff --git a/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb
index a140d25..7342b22 100644
--- a/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb
+++ b/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb
@@ -16,594 +16,582 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class GitAdapterTest < ActiveSupport::TestCase
-    REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
-
-    FELIX_HEX  = "Felix Sch\xC3\xA4fer"
-    CHAR_1_HEX = "\xc3\x9c"
-
-    ## Git, Mercurial and CVS path encodings are binary.
-    ## Subversion supports URL encoding for path.
-    ## Redmine Mercurial adapter and extension use URL encoding.
-    ## Git accepts only binary path in command line parameter.
-    ## So, there is no way to use binary command line parameter in JRuby.
-    JRUBY_SKIP     = (RUBY_PLATFORM == 'java')
-    JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
-
-    if File.directory?(REPOSITORY_PATH)
-      ## Ruby uses ANSI api to fork a process on Windows.
-      ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
-      ## and these are incompatible with ASCII.
-      ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
-      ## http://code.google.com/p/msysgit/issues/detail?id=80
-      ## So, Latin-1 path tests fail on Japanese Windows
-      WINDOWS_PASS = (Redmine::Platform.mswin? &&
-                      Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
-      WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
-
-      def setup
-        adapter_class = Redmine::Scm::Adapters::GitAdapter
-        assert adapter_class
-        assert adapter_class.client_command
-        assert_equal true, adapter_class.client_available
-        assert_equal true, adapter_class.client_version_above?([1])
-        assert_equal true, adapter_class.client_version_above?([1, 0])
-
-        @adapter = Redmine::Scm::Adapters::GitAdapter.new(
-                      REPOSITORY_PATH,
-                      nil,
-                      nil,
-                      nil,
-                      'ISO-8859-1'
-                   )
-        assert @adapter
-        @char_1 = CHAR_1_HEX.dup
-        @str_felix_hex  = FELIX_HEX.dup
-        if @char_1.respond_to?(:force_encoding)
-          @char_1.force_encoding('UTF-8')
-          @str_felix_hex.force_encoding('ASCII-8BIT')
-        end
-      end
 
-      def test_scm_version
-        to_test = { "git version 1.7.3.4\n"             => [1,7,3,4],
-                    "1.6.1\n1.7\n1.8"                   => [1,6,1],
-                    "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
-      end
+class GitAdapterTest < ActiveSupport::TestCase
+  REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
+
+  FELIX_HEX  = "Felix Sch\xC3\xA4fer"
+  CHAR_1_HEX = "\xc3\x9c"
+
+  ## Git, Mercurial and CVS path encodings are binary.
+  ## Subversion supports URL encoding for path.
+  ## Redmine Mercurial adapter and extension use URL encoding.
+  ## Git accepts only binary path in command line parameter.
+  ## So, there is no way to use binary command line parameter in JRuby.
+  JRUBY_SKIP     = (RUBY_PLATFORM == 'java')
+  JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
+
+  if File.directory?(REPOSITORY_PATH)
+    ## Ruby uses ANSI api to fork a process on Windows.
+    ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
+    ## and these are incompatible with ASCII.
+    ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
+    ## http://code.google.com/p/msysgit/issues/detail?id=80
+    ## So, Latin-1 path tests fail on Japanese Windows
+    WINDOWS_PASS = (Redmine::Platform.mswin? &&
+                    Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
+    WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
+
+    def setup
+      adapter_class = Redmine::Scm::Adapters::GitAdapter
+      assert adapter_class
+      assert adapter_class.client_command
+      assert_equal true, adapter_class.client_available
+      assert_equal true, adapter_class.client_version_above?([1])
+      assert_equal true, adapter_class.client_version_above?([1, 0])
+
+      @adapter = Redmine::Scm::Adapters::GitAdapter.new(
+                    REPOSITORY_PATH,
+                    nil,
+                    nil,
+                    nil,
+                    'ISO-8859-1'
+                 )
+      assert @adapter
+      @char_1 = CHAR_1_HEX.dup.force_encoding('UTF-8')
+      @str_felix_hex  = FELIX_HEX.dup.force_encoding('ASCII-8BIT')
+    end
 
-      def test_branches
-        brs = []
-        @adapter.branches.each do |b|
-          brs << b
-        end
-        assert_equal 6, brs.length
-        br_issue_8857 = brs[0]
-        assert_equal 'issue-8857', br_issue_8857.to_s 
-        assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision
-        assert_equal br_issue_8857.scmid, br_issue_8857.revision
-        assert_equal false, br_issue_8857.is_default
-        br_latin_1_path = brs[1]
-        assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s 
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision
-        assert_equal br_latin_1_path.scmid, br_latin_1_path.revision
-        assert_equal false, br_latin_1_path.is_default
-        br_master = brs[2]
-        assert_equal 'master', br_master.to_s
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision
-        assert_equal br_master.scmid, br_master.revision
-        assert_equal false, br_master.is_default
-        br_master_20120212 = brs[3]
-        assert_equal 'master-20120212', br_master_20120212.to_s
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision
-        assert_equal br_master_20120212.scmid, br_master_20120212.revision
-        assert_equal true, br_master_20120212.is_default
-        br_latin_1 = brs[-2]
-        assert_equal 'test-latin-1', br_latin_1.to_s
-        assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision
-        assert_equal br_latin_1.scmid, br_latin_1.revision
-        assert_equal false, br_latin_1.is_default
-        br_test = brs[-1]
-        assert_equal 'test_branch', br_test.to_s
-        assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision
-        assert_equal br_test.scmid, br_test.revision
-        assert_equal false, br_test.is_default
+    def test_scm_version
+      to_test = { "git version 1.7.3.4\n"             => [1,7,3,4],
+                  "1.6.1\n1.7\n1.8"                   => [1,6,1],
+                  "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
+      to_test.each do |s, v|
+        test_scm_version_for(s, v)
       end
+    end
 
-      def test_default_branch
-        assert_equal 'master-20120212', @adapter.default_branch
-      end
+    def test_branches
+      brs = []
+      @adapter.branches.each do |b|
+        brs << b
+      end
+      assert_equal 6, brs.length
+      br_issue_8857 = brs[0]
+      assert_equal 'issue-8857', br_issue_8857.to_s 
+      assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision
+      assert_equal br_issue_8857.scmid, br_issue_8857.revision
+      assert_equal false, br_issue_8857.is_default
+      br_latin_1_path = brs[1]
+      assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s 
+      assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision
+      assert_equal br_latin_1_path.scmid, br_latin_1_path.revision
+      assert_equal false, br_latin_1_path.is_default
+      br_master = brs[2]
+      assert_equal 'master', br_master.to_s
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision
+      assert_equal br_master.scmid, br_master.revision
+      assert_equal false, br_master.is_default
+      br_master_20120212 = brs[3]
+      assert_equal 'master-20120212', br_master_20120212.to_s
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision
+      assert_equal br_master_20120212.scmid, br_master_20120212.revision
+      assert_equal true, br_master_20120212.is_default
+      br_latin_1 = brs[-2]
+      assert_equal 'test-latin-1', br_latin_1.to_s
+      assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision
+      assert_equal br_latin_1.scmid, br_latin_1.revision
+      assert_equal false, br_latin_1.is_default
+      br_test = brs[-1]
+      assert_equal 'test_branch', br_test.to_s
+      assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision
+      assert_equal br_test.scmid, br_test.revision
+      assert_equal false, br_test.is_default
+    end
 
-      def test_tags
-        assert_equal  [
-              "tag00.lightweight",
-              "tag01.annotated",
-            ], @adapter.tags
-      end
+    def test_default_branch
+      assert_equal 'master-20120212', @adapter.default_branch
+    end
 
-      def test_revisions_master_all
-        revs1 = []
-        @adapter.revisions('', nil, "master",{}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 15, revs1.length
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
-
-        revs2 = []
-        @adapter.revisions('', nil, "master",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 15, revs2.length
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
-      end
+    def test_tags
+      assert_equal  [
+            "tag00.lightweight",
+            "tag01.annotated",
+          ], @adapter.tags
+    end
 
-      def test_revisions_master_merged_rev
-        revs1 = []
-        @adapter.revisions('',
-                           "713f4944648826f558cf548222f813dabe7cbb04",
-                           "master",
-                           {:reverse => true}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 8, revs1.length
-        assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier
-        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier
-        # 4a07fe31b is not a child of 713f49446
-        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier
-        # Merged revision
-        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
-
-        revs2 = []
-        @adapter.revisions('',
-                           "fba357b886984ee71185ad2065e65fc0417d9b92",
-                           "master",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 7, revs2.length
-        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier
-        # 4a07fe31b is not a child of fba357b8869
-        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier
-        # Merged revision
-        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
+    def test_revisions_master_all
+      revs1 = []
+      @adapter.revisions('', nil, "master",{}) do |rev|
+        revs1 << rev
       end
+      assert_equal 15, revs1.length
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier
+      assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
 
-      def test_revisions_branch_latin_1_path_encoding_all
-        revs1 = []
-        @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 8, revs1.length
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
-
-        revs2 = []
-        @adapter.revisions('', nil, "latin-1-path-encoding",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 8, revs2.length
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
+      revs2 = []
+      @adapter.revisions('', nil, "master",
+                         {:reverse => true}) do |rev|
+        revs2 << rev
       end
+      assert_equal 15, revs2.length
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
+      assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
+    end
 
-      def test_revisions_branch_latin_1_path_encoding_with_rev
-        revs1 = []
-        @adapter.revisions('',
-                           '7234cb2750b63f47bff735edc50a1c0a433c2518',
-                           "latin-1-path-encoding",
-                           {:reverse => true}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 7, revs1.length
-        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
+    def test_revisions_master_merged_rev
+      revs1 = []
+      @adapter.revisions('',
+                         "713f4944648826f558cf548222f813dabe7cbb04",
+                         "master",
+                         {:reverse => true}) do |rev|
+        revs1 << rev
+      end
+      assert_equal 8, revs1.length
+      assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier
+      assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier
+      # 4a07fe31b is not a child of 713f49446
+      assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier
+      # Merged revision
+      assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
+
+      revs2 = []
+      @adapter.revisions('',
+                         "fba357b886984ee71185ad2065e65fc0417d9b92",
+                         "master",
+                         {:reverse => true}) do |rev|
+        revs2 << rev
+      end
+      assert_equal 7, revs2.length
+      assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier
+      # 4a07fe31b is not a child of fba357b8869
+      assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier
+      # Merged revision
+      assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
+    end
 
-        revs2 = []
-        @adapter.revisions('',
-                           '57ca437c0acbbcb749821fdf3726a1367056d364',
-                           "latin-1-path-encoding",
-                           {:reverse => true}) do |rev|
-          revs2 << rev
-        end
-        assert_equal 3, revs2.length
-        assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
+    def test_revisions_branch_latin_1_path_encoding_all
+      revs1 = []
+      @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev|
+        revs1 << rev
       end
+      assert_equal 8, revs1.length
+      assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier
+      assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
 
-      def test_revisions_invalid_rev
-        assert_equal [], @adapter.revisions('', '1234abcd', "master")
-        assert_raise Redmine::Scm::Adapters::CommandFailed do
-          revs1 = []
-          @adapter.revisions('',
-                           '1234abcd',
-                           "master",
-                           {:reverse => true}) do |rev|
-            revs1 << rev
-          end
-        end
+      revs2 = []
+      @adapter.revisions('', nil, "latin-1-path-encoding",
+                         {:reverse => true}) do |rev|
+        revs2 << rev
       end
+      assert_equal 8, revs2.length
+      assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
+      assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
+    end
 
-      def test_revisions_includes_master_two_revs
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                            :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 2, revs1.length
-        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
-      end
+    def test_revisions_branch_latin_1_path_encoding_with_rev
+      revs1 = []
+      @adapter.revisions('',
+                         '7234cb2750b63f47bff735edc50a1c0a433c2518',
+                         "latin-1-path-encoding",
+                         {:reverse => true}) do |rev|
+        revs1 << rev
+      end
+      assert_equal 7, revs1.length
+      assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier
+      assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
+
+      revs2 = []
+      @adapter.revisions('',
+                         '57ca437c0acbbcb749821fdf3726a1367056d364',
+                         "latin-1-path-encoding",
+                         {:reverse => true}) do |rev|
+        revs2 << rev
+      end
+      assert_equal 3, revs2.length
+      assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier
+      assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
+    end
 
-      def test_revisions_includes_master_two_revs_from_origin
+    def test_revisions_invalid_rev
+      assert_equal [], @adapter.revisions('', '1234abcd', "master")
+      assert_raise Redmine::Scm::Adapters::CommandFailed do
         revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'],
-                            :excludes => []}) do |rev|
+        @adapter.revisions('',
+                         '1234abcd',
+                         "master",
+                         {:reverse => true}) do |rev|
           revs1 << rev
         end
-        assert_equal 2, revs1.length
-        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
-        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier
       end
+    end
 
-      def test_revisions_includes_merged_revs
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                            :excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 7, revs1.length
-        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier
-        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier
-        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
-      end
+    def test_revisions_includes_master_two_revs
+      revs1 = []
+      @adapter.revisions('', nil, nil,
+                         {:reverse => true,
+                          :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
+                          :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev|
+        revs1 << rev
+      end
+      assert_equal 2, revs1.length
+      assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
+    end
 
-      def test_revisions_includes_two_heads
-        revs1 = []
-        @adapter.revisions('', nil, nil,
-                           {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
-                                          '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'],
-                            :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43',
-                                          '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 4, revs1.length
-        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
-        assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier
-        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
-      end
+    def test_revisions_includes_master_two_revs_from_origin
+      revs1 = []
+      @adapter.revisions('', nil, nil,
+                         {:reverse => true,
+                          :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'],
+                          :excludes => []}) do |rev|
+        revs1 << rev
+      end
+      assert_equal 2, revs1.length
+      assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
+      assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier
+    end
 
-      def test_revisions_disjointed_histories_revisions
+    def test_revisions_includes_merged_revs
+      revs1 = []
+      @adapter.revisions('', nil, nil,
+                         {:reverse => true,
+                          :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
+                          :excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev|
+        revs1 << rev
+      end
+      assert_equal 7, revs1.length
+      assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier
+      assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier
+      assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
+    end
+
+    def test_revisions_includes_two_heads
+      revs1 = []
+      @adapter.revisions('', nil, nil,
+                         {:reverse => true,
+                          :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
+                                        '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'],
+                          :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43',
+                                        '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev|
+        revs1 << rev
+      end
+      assert_equal 4, revs1.length
+      assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
+      assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier
+      assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
+    end
+
+    def test_revisions_disjointed_histories_revisions
+      revs1 = []
+      @adapter.revisions('', nil, nil,
+                         {:reverse => true,
+                          :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
+                                        '92397af84d22f27389c822848ecd5b463c181583'],
+                          :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63',
+                                        '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev|
+        revs1 << rev
+      end
+      assert_equal 4, revs1.length
+      assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
+      assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
+      assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier
+      assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier
+    end
+
+    def test_revisions_invalid_rev_excludes
+      assert_equal [],
+                   @adapter.revisions('', nil, nil,
+                                      {:reverse => true,
+                                       :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
+                                       :excludes => ['0123abcd4567']})
+      assert_raise Redmine::Scm::Adapters::CommandFailed do
         revs1 = []
         @adapter.revisions('', nil, nil,
                            {:reverse => true,
-                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
-                                          '92397af84d22f27389c822848ecd5b463c181583'],
-                            :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63',
-                                          '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev|
+                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
+                            :excludes => ['0123abcd4567']}) do |rev|
           revs1 << rev
         end
-        assert_equal 4, revs1.length
-        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
-        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
-        assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier
-        assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier
-      end
-
-      def test_revisions_invalid_rev_excludes
-        assert_equal [],
-                     @adapter.revisions('', nil, nil,
-                                        {:reverse => true,
-                                         :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                                         :excludes => ['0123abcd4567']})
-        assert_raise Redmine::Scm::Adapters::CommandFailed do
-          revs1 = []
-          @adapter.revisions('', nil, nil,
-                             {:reverse => true,
-                              :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
-                              :excludes => ['0123abcd4567']}) do |rev|
-            revs1 << rev
-          end
-        end
       end
+    end
 
-      def test_getting_revisions_with_spaces_in_filename
-        assert_equal 1, @adapter.revisions("filemane with spaces.txt",
-                                           nil, "master").length
-      end
+    def test_getting_revisions_with_spaces_in_filename
+      assert_equal 1, @adapter.revisions("filemane with spaces.txt",
+                                         nil, "master").length
+    end
 
-      def test_parents
-        revs1 = []
-        @adapter.revisions('',
-                           nil,
-                           "master",
-                           {:reverse => true}) do |rev|
-          revs1 << rev
-        end
-        assert_equal 15, revs1.length
-        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
-                     revs1[0].identifier
-        assert_equal nil, revs1[0].parents
-        assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9",
-                     revs1[1].identifier
-        assert_equal 1, revs1[1].parents.length
-        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
-                     revs1[1].parents[0]
-        assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
-                     revs1[10].identifier
-        assert_equal 2, revs1[10].parents.length
-        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8",
-                     revs1[10].parents[0]
-        assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da",
-                     revs1[10].parents[1]
-      end
+    def test_parents
+      revs1 = []
+      @adapter.revisions('',
+                         nil,
+                         "master",
+                         {:reverse => true}) do |rev|
+        revs1 << rev
+      end
+      assert_equal 15, revs1.length
+      assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
+                   revs1[0].identifier
+      assert_equal nil, revs1[0].parents
+      assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9",
+                   revs1[1].identifier
+      assert_equal 1, revs1[1].parents.length
+      assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
+                   revs1[1].parents[0]
+      assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
+                   revs1[10].identifier
+      assert_equal 2, revs1[10].parents.length
+      assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8",
+                   revs1[10].parents[0]
+      assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da",
+                   revs1[10].parents[1]
+    end
 
-      def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
-        assert_equal " filename with a leading space.txt ",
-           @adapter.revisions(" filename with a leading space.txt ",
-                               nil, "master")[0].paths[0][:path]
-      end
+    def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
+      assert_equal " filename with a leading space.txt ",
+         @adapter.revisions(" filename with a leading space.txt ",
+                             nil, "master")[0].paths[0][:path]
+    end
 
-      def test_getting_entries_with_leading_and_trailing_spaces_in_filename
-        assert_equal " filename with a leading space.txt ",
-           @adapter.entries('',
-                   '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
-      end
+    def test_getting_entries_with_leading_and_trailing_spaces_in_filename
+      assert_equal " filename with a leading space.txt ",
+         @adapter.entries('',
+                 '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
+    end
 
-      def test_annotate
-        annotate = @adapter.annotate('sources/watchers_controller.rb')
-        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
-        assert_equal 41, annotate.lines.size
-        assert_equal "# This program is free software; you can redistribute it and/or",
-                     annotate.lines[4].strip
-        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
-                      annotate.revisions[4].identifier
-        assert_equal "jsmith", annotate.revisions[4].author
-      end
+    def test_annotate
+      annotate = @adapter.annotate('sources/watchers_controller.rb')
+      assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
+      assert_equal 41, annotate.lines.size
+      assert_equal "# This program is free software; you can redistribute it and/or",
+                   annotate.lines[4].strip
+      assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
+                    annotate.revisions[4].identifier
+      assert_equal "jsmith", annotate.revisions[4].author
+    end
 
-      def test_annotate_moved_file
-        annotate = @adapter.annotate('renamed_test.txt')
-        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
-        assert_equal 2, annotate.lines.size
-      end
+    def test_annotate_moved_file
+      annotate = @adapter.annotate('renamed_test.txt')
+      assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
+      assert_equal 2, annotate.lines.size
+    end
 
-      def test_last_rev
-        last_rev = @adapter.lastrev("README",
-                                    "4f26664364207fa8b1af9f8722647ab2d4ac5d43")
-        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
-        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
-        assert_equal "Adam Soltys <asoltys at gmail.com>", last_rev.author
-        assert_equal Time.gm(2009, 6, 24, 5, 27, 38), last_rev.time
-      end
+    def test_last_rev
+      last_rev = @adapter.lastrev("README",
+                                  "4f26664364207fa8b1af9f8722647ab2d4ac5d43")
+      assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
+      assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
+      assert_equal "Adam Soltys <asoltys at gmail.com>", last_rev.author
+      assert_equal Time.gm(2009, 6, 24, 5, 27, 38), last_rev.time
+    end
 
-      def test_last_rev_with_spaces_in_filename
-        last_rev = @adapter.lastrev("filemane with spaces.txt",
-                                    "ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
-        last_rev_author = last_rev.author
-        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
-        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
-        assert_equal "#{@str_felix_hex} <felix at fachschaften.org>",
-                       last_rev.author
-        assert_equal Time.gm(2010, 9, 18, 19, 59, 46), last_rev.time
-      end
+    def test_last_rev_with_spaces_in_filename
+      last_rev = @adapter.lastrev("filemane with spaces.txt",
+                                  "ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
+      last_rev_author = last_rev.author
+      assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
+      assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
+      assert_equal "#{@str_felix_hex} <felix at fachschaften.org>",
+                     last_rev.author
+      assert_equal Time.gm(2010, 9, 18, 19, 59, 46), last_rev.time
+    end
 
-      def test_latin_1_path
-        if WINDOWS_PASS
-          puts WINDOWS_SKIP_STR
-        elsif JRUBY_SKIP
-          puts JRUBY_SKIP_STR
-        else
-          p2 = "latin-1-dir/test-#{@char_1}-2.txt"
-          ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
-            assert @adapter.diff(p2, r1)
-            assert @adapter.cat(p2, r1)
-            assert_equal 1, @adapter.annotate(p2, r1).lines.length
-            ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
-              assert @adapter.diff(p2, r1, r2)
-            end
+    def test_latin_1_path
+      if WINDOWS_PASS
+        puts WINDOWS_SKIP_STR
+      elsif JRUBY_SKIP
+        puts JRUBY_SKIP_STR
+      else
+        p2 = "latin-1-dir/test-#{@char_1}-2.txt"
+        ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
+          assert @adapter.diff(p2, r1)
+          assert @adapter.cat(p2, r1)
+          assert_equal 1, @adapter.annotate(p2, r1).lines.length
+          ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
+            assert @adapter.diff(p2, r1, r2)
           end
         end
       end
+    end
 
-      def test_latin_1_user_annotate
-        ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
-          annotate = @adapter.annotate(" filename with a leading space.txt ", r1)
-          assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
-          assert_equal 1, annotate.lines.size
-          assert_equal "And this is a file with a leading and trailing space...",
-                       annotate.lines[0].strip
-          assert_equal "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
-                       annotate.revisions[0].identifier
-          assert_equal @str_felix_hex, annotate.revisions[0].author
-        end
+    def test_latin_1_user_annotate
+      ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
+        annotate = @adapter.annotate(" filename with a leading space.txt ", r1)
+        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
+        assert_equal 1, annotate.lines.size
+        assert_equal "And this is a file with a leading and trailing space...",
+                     annotate.lines[0].strip
+        assert_equal "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
+                     annotate.revisions[0].identifier
+        assert_equal @str_felix_hex, annotate.revisions[0].author
       end
+    end
 
-      def test_entries_tag
-        entries1 = @adapter.entries(nil, 'tag01.annotated',
-                                    options = {:report_last_commit => true})
-        assert entries1
-        assert_equal 3, entries1.size
-        assert_equal 'sources', entries1[1].name
-        assert_equal 'sources', entries1[1].path
-        assert_equal 'dir', entries1[1].kind
-        readme = entries1[2]
-        assert_equal 'README', readme.name
-        assert_equal 'README', readme.path
-        assert_equal 'file', readme.kind
-        assert_equal 27, readme.size
-        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
-        assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
-      end
+    def test_entries_tag
+      entries1 = @adapter.entries(nil, 'tag01.annotated',
+                                  options = {:report_last_commit => true})
+      assert entries1
+      assert_equal 3, entries1.size
+      assert_equal 'sources', entries1[1].name
+      assert_equal 'sources', entries1[1].path
+      assert_equal 'dir', entries1[1].kind
+      readme = entries1[2]
+      assert_equal 'README', readme.name
+      assert_equal 'README', readme.path
+      assert_equal 'file', readme.kind
+      assert_equal 27, readme.size
+      assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
+      assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
+    end
 
-      def test_entries_branch
-        entries1 = @adapter.entries(nil, 'test_branch',
-                                    options = {:report_last_commit => true})
-        assert entries1
-        assert_equal 4, entries1.size
-        assert_equal 'sources', entries1[1].name
-        assert_equal 'sources', entries1[1].path
-        assert_equal 'dir', entries1[1].kind
-        readme = entries1[2]
-        assert_equal 'README', readme.name
-        assert_equal 'README', readme.path
-        assert_equal 'file', readme.kind
-        assert_equal 159, readme.size
-        assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
-        assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
-      end
+    def test_entries_branch
+      entries1 = @adapter.entries(nil, 'test_branch',
+                                  options = {:report_last_commit => true})
+      assert entries1
+      assert_equal 4, entries1.size
+      assert_equal 'sources', entries1[1].name
+      assert_equal 'sources', entries1[1].path
+      assert_equal 'dir', entries1[1].kind
+      readme = entries1[2]
+      assert_equal 'README', readme.name
+      assert_equal 'README', readme.path
+      assert_equal 'file', readme.kind
+      assert_equal 159, readme.size
+      assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
+      assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
+    end
 
-      def test_entries_wrong_path_encoding
-        adpt = Redmine::Scm::Adapters::GitAdapter.new(
-                      REPOSITORY_PATH,
-                      nil,
-                      nil,
-                      nil,
-                      'EUC-JP'
-                   )
-        entries1 = adpt.entries('latin-1-dir', '64f1f3e8')
-        assert entries1
-        assert_equal 3, entries1.size
-        f1 = entries1[1]
-        assert_equal nil, f1.name
-        assert_equal nil, f1.path
-        assert_equal 'file', f1.kind
-      end
+    def test_entries_wrong_path_encoding
+      adpt = Redmine::Scm::Adapters::GitAdapter.new(
+                    REPOSITORY_PATH,
+                    nil,
+                    nil,
+                    nil,
+                    'EUC-JP'
+                 )
+      entries1 = adpt.entries('latin-1-dir', '64f1f3e8')
+      assert entries1
+      assert_equal 3, entries1.size
+      f1 = entries1[1]
+      assert_equal nil, f1.name
+      assert_equal nil, f1.path
+      assert_equal 'file', f1.kind
+    end
+
+    def test_entries_latin_1_files
+      entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
+      assert entries1
+      assert_equal 3, entries1.size
+      f1 = entries1[1]
+      assert_equal "test-#{@char_1}-2.txt", f1.name
+      assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
+      assert_equal 'file', f1.kind
+    end
 
-      def test_entries_latin_1_files
-        entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
+    def test_entries_latin_1_dir
+      if WINDOWS_PASS
+        puts WINDOWS_SKIP_STR
+      elsif JRUBY_SKIP
+        puts JRUBY_SKIP_STR
+      else
+        entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
+                                    '1ca7f5ed')
         assert entries1
         assert_equal 3, entries1.size
         f1 = entries1[1]
         assert_equal "test-#{@char_1}-2.txt", f1.name
-        assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
+        assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
         assert_equal 'file', f1.kind
       end
+    end
 
-      def test_entries_latin_1_dir
-        if WINDOWS_PASS
-          puts WINDOWS_SKIP_STR
-        elsif JRUBY_SKIP
-          puts JRUBY_SKIP_STR
-        else
-          entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
-                                      '1ca7f5ed')
-          assert entries1
-          assert_equal 3, entries1.size
-          f1 = entries1[1]
-          assert_equal "test-#{@char_1}-2.txt", f1.name
-          assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
-          assert_equal 'file', f1.kind
-        end
-      end
-
-      def test_entry
-        entry = @adapter.entry()
-        assert_equal "", entry.path
+    def test_entry
+      entry = @adapter.entry()
+      assert_equal "", entry.path
+      assert_equal "dir", entry.kind
+      entry = @adapter.entry('')
+      assert_equal "", entry.path
+      assert_equal "dir", entry.kind
+      assert_nil @adapter.entry('invalid')
+      assert_nil @adapter.entry('/invalid')
+      assert_nil @adapter.entry('/invalid/')
+      assert_nil @adapter.entry('invalid/invalid')
+      assert_nil @adapter.entry('invalid/invalid/')
+      assert_nil @adapter.entry('/invalid/invalid')
+      assert_nil @adapter.entry('/invalid/invalid/')
+      ["README", "/README"].each do |path|
+        entry = @adapter.entry(path, '7234cb2750b63f')
+        assert_equal "README", entry.path
+        assert_equal "file", entry.kind
+      end
+      ["sources", "/sources", "/sources/"].each do |path|
+        entry = @adapter.entry(path, '7234cb2750b63f')
+        assert_equal "sources", entry.path
         assert_equal "dir", entry.kind
-        entry = @adapter.entry('')
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        assert_nil @adapter.entry('invalid')
-        assert_nil @adapter.entry('/invalid')
-        assert_nil @adapter.entry('/invalid/')
-        assert_nil @adapter.entry('invalid/invalid')
-        assert_nil @adapter.entry('invalid/invalid/')
-        assert_nil @adapter.entry('/invalid/invalid')
-        assert_nil @adapter.entry('/invalid/invalid/')
-        ["README", "/README"].each do |path|
-          entry = @adapter.entry(path, '7234cb2750b63f')
-          assert_equal "README", entry.path
-          assert_equal "file", entry.kind
-        end
-        ["sources", "/sources", "/sources/"].each do |path|
-          entry = @adapter.entry(path, '7234cb2750b63f')
-          assert_equal "sources", entry.path
-          assert_equal "dir", entry.kind
-        end
-        ["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path|
-          entry = @adapter.entry(path, '7234cb2750b63f')
-          assert_equal "sources/watchers_controller.rb", entry.path
-          assert_equal "file", entry.kind
-        end
       end
-
-      def test_path_encoding_default_utf8
-        adpt1 = Redmine::Scm::Adapters::GitAdapter.new(
-                                  REPOSITORY_PATH
-                                )
-        assert_equal "UTF-8", adpt1.path_encoding
-        adpt2 = Redmine::Scm::Adapters::GitAdapter.new(
-                                  REPOSITORY_PATH,
-                                  nil,
-                                  nil,
-                                  nil,
-                                  ""
-                                )
-        assert_equal "UTF-8", adpt2.path_encoding
+      ["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path|
+        entry = @adapter.entry(path, '7234cb2750b63f')
+        assert_equal "sources/watchers_controller.rb", entry.path
+        assert_equal "file", entry.kind
       end
+    end
 
-      def test_cat_path_invalid
-        assert_nil @adapter.cat('invalid')
-      end
+    def test_path_encoding_default_utf8
+      adpt1 = Redmine::Scm::Adapters::GitAdapter.new(
+                                REPOSITORY_PATH
+                              )
+      assert_equal "UTF-8", adpt1.path_encoding
+      adpt2 = Redmine::Scm::Adapters::GitAdapter.new(
+                                REPOSITORY_PATH,
+                                nil,
+                                nil,
+                                nil,
+                                ""
+                              )
+      assert_equal "UTF-8", adpt2.path_encoding
+    end
 
-      def test_cat_revision_invalid
-        assert     @adapter.cat('README')
-        assert_nil @adapter.cat('README', '1234abcd5678')
-      end
+    def test_cat_path_invalid
+      assert_nil @adapter.cat('invalid')
+    end
 
-      def test_diff_path_invalid
-        assert_equal [], @adapter.diff('invalid', '713f4944648826f5')
-      end
+    def test_cat_revision_invalid
+      assert     @adapter.cat('README')
+      assert_nil @adapter.cat('README', '1234abcd5678')
+    end
 
-      def test_diff_revision_invalid
-        assert_nil @adapter.diff(nil, '1234abcd5678')
-        assert_nil @adapter.diff(nil, '713f4944648826f5', '1234abcd5678')
-        assert_nil @adapter.diff(nil, '1234abcd5678', '713f4944648826f5')
-      end
+    def test_diff_path_invalid
+      assert_equal [], @adapter.diff('invalid', '713f4944648826f5')
+    end
 
-      def test_annotate_path_invalid
-        assert_nil @adapter.annotate('invalid')
-      end
+    def test_diff_revision_invalid
+      assert_nil @adapter.diff(nil, '1234abcd5678')
+      assert_nil @adapter.diff(nil, '713f4944648826f5', '1234abcd5678')
+      assert_nil @adapter.diff(nil, '1234abcd5678', '713f4944648826f5')
+    end
 
-      def test_annotate_revision_invalid
-        assert     @adapter.annotate('README')
-        assert_nil @adapter.annotate('README', '1234abcd5678')
-      end
+    def test_annotate_path_invalid
+      assert_nil @adapter.annotate('invalid')
+    end
 
-      private
+    def test_annotate_revision_invalid
+      assert     @adapter.annotate('README')
+      assert_nil @adapter.annotate('README', '1234abcd5678')
+    end
 
-      def test_scm_version_for(scm_command_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
-        assert_equal version, @adapter.class.scm_command_version
-      end
+    private
 
-    else
-      puts "Git test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
+    def test_scm_version_for(scm_command_version, version)
+      @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
+      assert_equal version, @adapter.class.scm_command_version
     end
-  end
 
-rescue LoadError
-  class GitMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
+  else
+    puts "Git test repository NOT FOUND. Skipping unit tests !!!"
+    def test_fake; assert true end
   end
 end
diff --git a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
index 7f062d1..99fbec6 100644
--- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
+++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
@@ -16,221 +16,184 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require File.expand_path('../../../../../../test_helper', __FILE__)
-begin
-  require 'mocha/setup'
-
-  class MercurialAdapterTest < ActiveSupport::TestCase
-    HELPERS_DIR        = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR
-    TEMPLATE_NAME      = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
-    TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
-
-    REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
-    CHAR_1_HEX = "\xc3\x9c"
-
-    if File.directory?(REPOSITORY_PATH)
-      def setup
-        adapter_class = Redmine::Scm::Adapters::MercurialAdapter
-        assert adapter_class
-        assert adapter_class.client_command
-        assert_equal true, adapter_class.client_available
-        assert_equal true, adapter_class.client_version_above?([0, 9, 5])
-
-        @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(
-                              REPOSITORY_PATH,
-                              nil,
-                              nil,
-                              nil,
-                             'ISO-8859-1')
-        @diff_c_support = true
-        @char_1        = CHAR_1_HEX.dup
-        @tag_char_1    = "tag-#{CHAR_1_HEX}-00"
-        @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
-        @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
-        if @tag_char_1.respond_to?(:force_encoding)
-          @char_1.force_encoding('UTF-8')
-          @tag_char_1.force_encoding('UTF-8')
-          @branch_char_0.force_encoding('UTF-8')
-          @branch_char_1.force_encoding('UTF-8')
-        end
-      end
 
-      def test_hgversion
-        to_test = { "Mercurial Distributed SCM (version 0.9.5)\n"  => [0,9,5],
-                    "Mercurial Distributed SCM (1.0)\n"            => [1,0],
-                    "Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
-                    "Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
-                    "Mercurial Distributed SCM (1916e629a29d)\n"   => nil,
-                    "Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
-                    "(1.6)\n(1.7)\n(1.8)"                          => [1,6],
-                    "(1.7.1)\r\n(1.8.1)\r\n(1.9.1)"                => [1,7,1]}
-
-        to_test.each do |s, v|
-          test_hgversion_for(s, v)
-        end
-      end
+class MercurialAdapterTest < ActiveSupport::TestCase
+  HELPERS_DIR        = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR
+  TEMPLATE_NAME      = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
+  TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
+
+  REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
+  CHAR_1_HEX = "\xc3\x9c"
+
+  if File.directory?(REPOSITORY_PATH)
+    def setup
+      adapter_class = Redmine::Scm::Adapters::MercurialAdapter
+      assert adapter_class
+      assert adapter_class.client_command
+      assert_equal true, adapter_class.client_available
+      assert_equal true, adapter_class.client_version_above?([0, 9, 5])
+
+      @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(
+                            REPOSITORY_PATH,
+                            nil,
+                            nil,
+                            nil,
+                           'ISO-8859-1')
+      @diff_c_support = true
+      @char_1        = CHAR_1_HEX.dup.force_encoding('UTF-8')
+      @tag_char_1    = "tag-#{CHAR_1_HEX}-00".force_encoding('UTF-8')
+      @branch_char_0 = "branch-#{CHAR_1_HEX}-00".force_encoding('UTF-8')
+      @branch_char_1 = "branch-#{CHAR_1_HEX}-01".force_encoding('UTF-8')
+    end
 
-      def test_template_path
-        to_test = {
-                    [1,2]    => "1.0",
-                    []       => "1.0",
-                    [1,2,1]  => "1.0",
-                    [1,7]    => "1.0",
-                    [1,7,1]  => "1.0",
-                    [2,0]    => "1.0",
-                   }
-        to_test.each do |v, template|
-          test_template_path_for(v, template)
-        end
+    def test_hgversion
+      to_test = { "Mercurial Distributed SCM (version 0.9.5)\n"  => [0,9,5],
+                  "Mercurial Distributed SCM (1.0)\n"            => [1,0],
+                  "Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
+                  "Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
+                  "Mercurial Distributed SCM (1916e629a29d)\n"   => nil,
+                  "Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
+                  "(1.6)\n(1.7)\n(1.8)"                          => [1,6],
+                  "(1.7.1)\r\n(1.8.1)\r\n(1.9.1)"                => [1,7,1]}
+
+      to_test.each do |s, v|
+        test_hgversion_for(s, v)
       end
+    end
 
-      def test_info
-        [REPOSITORY_PATH, REPOSITORY_PATH + "/",
-             REPOSITORY_PATH + "//"].each do |repo|
-          adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo)
-          repo_path =  adp.info.root_url.gsub(/\\/, "/")
-          assert_equal REPOSITORY_PATH, repo_path
-          assert_equal '33', adp.info.lastrev.revision
-          assert_equal '2e6d546429230f377d7d19c2078abd2dd909f235',adp.info.lastrev.scmid
-        end
+    def test_template_path
+      to_test = {
+                  [1,2]    => "1.0",
+                  []       => "1.0",
+                  [1,2,1]  => "1.0",
+                  [1,7]    => "1.0",
+                  [1,7,1]  => "1.0",
+                  [2,0]    => "1.0",
+                 }
+      to_test.each do |v, template|
+        test_template_path_for(v, template)
       end
+    end
 
-      def test_revisions
-        revisions = @adapter.revisions(nil, 2, 4)
-        assert_equal 3, revisions.size
-        assert_equal '2', revisions[0].revision
-        assert_equal '400bb86721098697c7d17b3724c794c57636de70', revisions[0].scmid
-        assert_equal '4', revisions[2].revision
-        assert_equal 'def6d2f1254a56fb8fbe9ec3b5c0451674dbd8b8', revisions[2].scmid
-
-        revisions = @adapter.revisions(nil, 2, 4, {:limit => 2})
-        assert_equal 2, revisions.size
-        assert_equal '2', revisions[0].revision
-        assert_equal '400bb86721098697c7d17b3724c794c57636de70', revisions[0].scmid
+    def test_info
+      [REPOSITORY_PATH, REPOSITORY_PATH + "/",
+           REPOSITORY_PATH + "//"].each do |repo|
+        adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo)
+        repo_path =  adp.info.root_url.gsub(/\\/, "/")
+        assert_equal REPOSITORY_PATH, repo_path
+        assert_equal '33', adp.info.lastrev.revision
+        assert_equal '2e6d546429230f377d7d19c2078abd2dd909f235',adp.info.lastrev.scmid
       end
+    end
 
-      def test_parents
-        revs1 = @adapter.revisions(nil, 0, 0)
-        assert_equal 1, revs1.size
-        assert_equal [], revs1[0].parents
-        revs2 = @adapter.revisions(nil, 1, 1)
-        assert_equal 1, revs2.size
-        assert_equal 1, revs2[0].parents.size
-        assert_equal "0885933ad4f68d77c2649cd11f8311276e7ef7ce", revs2[0].parents[0]
-        revs3 = @adapter.revisions(nil, 30, 30)
-        assert_equal 1, revs3.size
-        assert_equal 2, revs3[0].parents.size
-        assert_equal "a94b0528f24fe05ebaef496ae0500bb050772e36", revs3[0].parents[0]
-        assert_equal "3a330eb329586ea2adb3f83237c23310e744ebe9", revs3[0].parents[1]
-      end
+    def test_revisions
+      revisions = @adapter.revisions(nil, 2, 4)
+      assert_equal 3, revisions.size
+      assert_equal '2', revisions[0].revision
+      assert_equal '400bb86721098697c7d17b3724c794c57636de70', revisions[0].scmid
+      assert_equal '4', revisions[2].revision
+      assert_equal 'def6d2f1254a56fb8fbe9ec3b5c0451674dbd8b8', revisions[2].scmid
+
+      revisions = @adapter.revisions(nil, 2, 4, {:limit => 2})
+      assert_equal 2, revisions.size
+      assert_equal '2', revisions[0].revision
+      assert_equal '400bb86721098697c7d17b3724c794c57636de70', revisions[0].scmid
+    end
 
-      def test_diff
-        if @adapter.class.client_version_above?([1, 2])
-          assert_nil @adapter.diff(nil, '100000')
-        end
-        assert_nil @adapter.diff(nil, '100000', '200000')
-        [2, '400bb8672109', '400', 400].each do |r1|
-          diff1 = @adapter.diff(nil, r1)
-          if @diff_c_support
-            assert_equal 28, diff1.size
-            buf = diff1[24].gsub(/\r\n|\r|\n/, "")
-            assert_equal "+    return true unless klass.respond_to?('watched_by')", buf
-          else
-            assert_equal 0, diff1.size
-          end
-          [4, 'def6d2f1254a'].each do |r2|
-            diff2 = @adapter.diff(nil, r1, r2)
-            assert_equal 49, diff2.size
-            buf =  diff2[41].gsub(/\r\n|\r|\n/, "")
-            assert_equal "+class WelcomeController < ApplicationController", buf
-            diff3 = @adapter.diff('sources/watchers_controller.rb', r1, r2)
-            assert_equal 20, diff3.size
-            buf =  diff3[12].gsub(/\r\n|\r|\n/, "")
-            assert_equal "+    @watched.remove_watcher(user)", buf
-
-            diff4 = @adapter.diff(nil, r2, r1)
-            assert_equal 49, diff4.size
-            buf =  diff4[41].gsub(/\r\n|\r|\n/, "")
-            assert_equal "-class WelcomeController < ApplicationController", buf
-            diff5 = @adapter.diff('sources/watchers_controller.rb', r2, r1)
-            assert_equal 20, diff5.size
-            buf =  diff5[9].gsub(/\r\n|\r|\n/, "")
-            assert_equal "-    @watched.remove_watcher(user)", buf
-          end
-        end
-      end
+    def test_parents
+      revs1 = @adapter.revisions(nil, 0, 0)
+      assert_equal 1, revs1.size
+      assert_equal [], revs1[0].parents
+      revs2 = @adapter.revisions(nil, 1, 1)
+      assert_equal 1, revs2.size
+      assert_equal 1, revs2[0].parents.size
+      assert_equal "0885933ad4f68d77c2649cd11f8311276e7ef7ce", revs2[0].parents[0]
+      revs3 = @adapter.revisions(nil, 30, 30)
+      assert_equal 1, revs3.size
+      assert_equal 2, revs3[0].parents.size
+      assert_equal "a94b0528f24fe05ebaef496ae0500bb050772e36", revs3[0].parents[0]
+      assert_equal "3a330eb329586ea2adb3f83237c23310e744ebe9", revs3[0].parents[1]
+    end
 
-      def test_diff_made_by_revision
+    def test_diff
+      if @adapter.class.client_version_above?([1, 2])
+        assert_nil @adapter.diff(nil, '100000')
+      end
+      assert_nil @adapter.diff(nil, '100000', '200000')
+      [2, '400bb8672109', '400', 400].each do |r1|
+        diff1 = @adapter.diff(nil, r1)
         if @diff_c_support
-          [24, '24', '4cddb4e45f52'].each do |r1|
-            diff1 = @adapter.diff(nil, r1)
-            assert_equal 5, diff1.size
-            buf = diff1[4].gsub(/\r\n|\r|\n/, "")
-            assert_equal '+0885933ad4f68d77c2649cd11f8311276e7ef7ce tag-init-revision', buf
-          end
+          assert_equal 28, diff1.size
+          buf = diff1[24].gsub(/\r\n|\r|\n/, "")
+          assert_equal "+    return true unless klass.respond_to?('watched_by')", buf
+        else
+          assert_equal 0, diff1.size
+        end
+        [4, 'def6d2f1254a'].each do |r2|
+          diff2 = @adapter.diff(nil, r1, r2)
+          assert_equal 49, diff2.size
+          buf =  diff2[41].gsub(/\r\n|\r|\n/, "")
+          assert_equal "+class WelcomeController < ApplicationController", buf
+          diff3 = @adapter.diff('sources/watchers_controller.rb', r1, r2)
+          assert_equal 20, diff3.size
+          buf =  diff3[12].gsub(/\r\n|\r|\n/, "")
+          assert_equal "+    @watched.remove_watcher(user)", buf
+
+          diff4 = @adapter.diff(nil, r2, r1)
+          assert_equal 49, diff4.size
+          buf =  diff4[41].gsub(/\r\n|\r|\n/, "")
+          assert_equal "-class WelcomeController < ApplicationController", buf
+          diff5 = @adapter.diff('sources/watchers_controller.rb', r2, r1)
+          assert_equal 20, diff5.size
+          buf =  diff5[9].gsub(/\r\n|\r|\n/, "")
+          assert_equal "-    @watched.remove_watcher(user)", buf
         end
       end
+    end
 
-      def test_cat
-        [2, '400bb8672109', '400', 400].each do |r|
-          buf = @adapter.cat('sources/welcome_controller.rb', r)
-          assert buf
-          lines = buf.split("\r\n")
-          assert_equal 25, lines.length
-          assert_equal 'class WelcomeController < ApplicationController', lines[17]
+    def test_diff_made_by_revision
+      if @diff_c_support
+        [24, '24', '4cddb4e45f52'].each do |r1|
+          diff1 = @adapter.diff(nil, r1)
+          assert_equal 5, diff1.size
+          buf = diff1[4].gsub(/\r\n|\r|\n/, "")
+          assert_equal '+0885933ad4f68d77c2649cd11f8311276e7ef7ce tag-init-revision', buf
         end
-        assert_nil @adapter.cat('sources/welcome_controller.rb')
       end
+    end
 
-      def test_annotate
-        assert_equal [], @adapter.annotate("sources/welcome_controller.rb").lines
-        [2, '400bb8672109', '400', 400].each do |r|
-          ann = @adapter.annotate('sources/welcome_controller.rb', r)
-          assert ann
-          assert_equal '1', ann.revisions[17].revision
-          assert_equal '9d5b5b004199', ann.revisions[17].identifier
-          assert_equal 'jsmith', ann.revisions[0].author
-          assert_equal 25, ann.lines.length
-          assert_equal 'class WelcomeController < ApplicationController', ann.lines[17]
-        end
+    def test_cat
+      [2, '400bb8672109', '400', 400].each do |r|
+        buf = @adapter.cat('sources/welcome_controller.rb', r)
+        assert buf
+        lines = buf.split("\r\n")
+        assert_equal 25, lines.length
+        assert_equal 'class WelcomeController < ApplicationController', lines[17]
       end
+      assert_nil @adapter.cat('sources/welcome_controller.rb')
+    end
 
-      def test_entries
-        assert_nil @adapter.entries(nil, '100000')
-
-        assert_equal 1, @adapter.entries("sources", 3).size
-        assert_equal 1, @adapter.entries("sources", 'b3a615152df8').size
-
-        [2, '400bb8672109', '400', 400].each do |r|
-          entries1 = @adapter.entries(nil, r)
-          assert entries1
-          assert_equal 3, entries1.size
-          assert_equal 'sources', entries1[1].name
-          assert_equal 'sources', entries1[1].path
-          assert_equal 'dir', entries1[1].kind
-          readme = entries1[2]
-          assert_equal 'README', readme.name
-          assert_equal 'README', readme.path
-          assert_equal 'file', readme.kind
-          assert_equal 27, readme.size
-          assert_equal '1', readme.lastrev.revision
-          assert_equal '9d5b5b00419901478496242e0768deba1ce8c51e', readme.lastrev.identifier
-          # 2007-12-14 10:24:01 +0100
-          assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
-
-          entries2 = @adapter.entries('sources', r)
-          assert entries2
-          assert_equal 2, entries2.size
-          assert_equal 'watchers_controller.rb', entries2[0].name
-          assert_equal 'sources/watchers_controller.rb', entries2[0].path
-          assert_equal 'file', entries2[0].kind
-          assert_equal 'welcome_controller.rb', entries2[1].name
-          assert_equal 'sources/welcome_controller.rb', entries2[1].path
-          assert_equal 'file', entries2[1].kind
-        end
+    def test_annotate
+      assert_equal [], @adapter.annotate("sources/welcome_controller.rb").lines
+      [2, '400bb8672109', '400', 400].each do |r|
+        ann = @adapter.annotate('sources/welcome_controller.rb', r)
+        assert ann
+        assert_equal '1', ann.revisions[17].revision
+        assert_equal '9d5b5b004199', ann.revisions[17].identifier
+        assert_equal 'jsmith', ann.revisions[0].author
+        assert_equal 25, ann.lines.length
+        assert_equal 'class WelcomeController < ApplicationController', ann.lines[17]
       end
+    end
+
+    def test_entries
+      assert_nil @adapter.entries(nil, '100000')
 
-      def test_entries_tag
-        entries1 = @adapter.entries(nil, 'tag_test.00')
+      assert_equal 1, @adapter.entries("sources", 3).size
+      assert_equal 1, @adapter.entries("sources", 'b3a615152df8').size
+
+      [2, '400bb8672109', '400', 400].each do |r|
+        entries1 = @adapter.entries(nil, r)
         assert entries1
         assert_equal 3, entries1.size
         assert_equal 'sources', entries1[1].name
@@ -240,236 +203,260 @@ begin
         assert_equal 'README', readme.name
         assert_equal 'README', readme.path
         assert_equal 'file', readme.kind
-        assert_equal 21, readme.size
-        assert_equal '0', readme.lastrev.revision
-        assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', readme.lastrev.identifier
-        # 2007-12-14 10:22:52 +0100
-        assert_equal Time.gm(2007, 12, 14, 9, 22, 52), readme.lastrev.time
+        assert_equal 27, readme.size
+        assert_equal '1', readme.lastrev.revision
+        assert_equal '9d5b5b00419901478496242e0768deba1ce8c51e', readme.lastrev.identifier
+        # 2007-12-14 10:24:01 +0100
+        assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
+
+        entries2 = @adapter.entries('sources', r)
+        assert entries2
+        assert_equal 2, entries2.size
+        assert_equal 'watchers_controller.rb', entries2[0].name
+        assert_equal 'sources/watchers_controller.rb', entries2[0].path
+        assert_equal 'file', entries2[0].kind
+        assert_equal 'welcome_controller.rb', entries2[1].name
+        assert_equal 'sources/welcome_controller.rb', entries2[1].path
+        assert_equal 'file', entries2[1].kind
       end
+    end
 
-      def test_entries_branch
-        entries1 = @adapter.entries(nil, 'test-branch-00')
-        assert entries1
-        assert_equal 5, entries1.size
-        assert_equal 'sql_escape', entries1[2].name
-        assert_equal 'sql_escape', entries1[2].path
-        assert_equal 'dir', entries1[2].kind
-        readme = entries1[4]
-        assert_equal 'README', readme.name
-        assert_equal 'README', readme.path
-        assert_equal 'file', readme.kind
-        assert_equal 365, readme.size
-        assert_equal '8', readme.lastrev.revision
-        assert_equal 'c51f5bb613cd60793c2a9fe9df29332e74bb949f', readme.lastrev.identifier
-        # 2001-02-01 00:00:00 -0900
-        assert_equal Time.gm(2001, 2, 1, 9, 0, 0), readme.lastrev.time
-      end
+    def test_entries_tag
+      entries1 = @adapter.entries(nil, 'tag_test.00')
+      assert entries1
+      assert_equal 3, entries1.size
+      assert_equal 'sources', entries1[1].name
+      assert_equal 'sources', entries1[1].path
+      assert_equal 'dir', entries1[1].kind
+      readme = entries1[2]
+      assert_equal 'README', readme.name
+      assert_equal 'README', readme.path
+      assert_equal 'file', readme.kind
+      assert_equal 21, readme.size
+      assert_equal '0', readme.lastrev.revision
+      assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', readme.lastrev.identifier
+      # 2007-12-14 10:22:52 +0100
+      assert_equal Time.gm(2007, 12, 14, 9, 22, 52), readme.lastrev.time
+    end
 
-      def test_entry
-        entry = @adapter.entry()
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        entry = @adapter.entry('')
-        assert_equal "", entry.path
-        assert_equal "dir", entry.kind
-        assert_nil @adapter.entry('invalid')
-        assert_nil @adapter.entry('/invalid')
-        assert_nil @adapter.entry('/invalid/')
-        assert_nil @adapter.entry('invalid/invalid')
-        assert_nil @adapter.entry('invalid/invalid/')
-        assert_nil @adapter.entry('/invalid/invalid')
-        assert_nil @adapter.entry('/invalid/invalid/')
-        ["README", "/README"].each do |path|
-          ["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
-            entry = @adapter.entry(path, rev)
-            assert_equal "README", entry.path
-            assert_equal "file", entry.kind
-            assert_equal '0', entry.lastrev.revision
-            assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', entry.lastrev.identifier
-          end
+    def test_entries_branch
+      entries1 = @adapter.entries(nil, 'test-branch-00')
+      assert entries1
+      assert_equal 5, entries1.size
+      assert_equal 'sql_escape', entries1[2].name
+      assert_equal 'sql_escape', entries1[2].path
+      assert_equal 'dir', entries1[2].kind
+      readme = entries1[4]
+      assert_equal 'README', readme.name
+      assert_equal 'README', readme.path
+      assert_equal 'file', readme.kind
+      assert_equal 365, readme.size
+      assert_equal '8', readme.lastrev.revision
+      assert_equal 'c51f5bb613cd60793c2a9fe9df29332e74bb949f', readme.lastrev.identifier
+      # 2001-02-01 00:00:00 -0900
+      assert_equal Time.gm(2001, 2, 1, 9, 0, 0), readme.lastrev.time
+    end
+
+    def test_entry
+      entry = @adapter.entry()
+      assert_equal "", entry.path
+      assert_equal "dir", entry.kind
+      entry = @adapter.entry('')
+      assert_equal "", entry.path
+      assert_equal "dir", entry.kind
+      assert_nil @adapter.entry('invalid')
+      assert_nil @adapter.entry('/invalid')
+      assert_nil @adapter.entry('/invalid/')
+      assert_nil @adapter.entry('invalid/invalid')
+      assert_nil @adapter.entry('invalid/invalid/')
+      assert_nil @adapter.entry('/invalid/invalid')
+      assert_nil @adapter.entry('/invalid/invalid/')
+      ["README", "/README"].each do |path|
+        ["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
+          entry = @adapter.entry(path, rev)
+          assert_equal "README", entry.path
+          assert_equal "file", entry.kind
+          assert_equal '0', entry.lastrev.revision
+          assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', entry.lastrev.identifier
         end
-        ["sources", "/sources", "/sources/"].each do |path|
-          ["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
-            entry = @adapter.entry(path, rev)
-            assert_equal "sources", entry.path
-            assert_equal "dir", entry.kind
-          end
+      end
+      ["sources", "/sources", "/sources/"].each do |path|
+        ["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
+          entry = @adapter.entry(path, rev)
+          assert_equal "sources", entry.path
+          assert_equal "dir", entry.kind
         end
-        ["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path|
-          ["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
-            entry = @adapter.entry(path, rev)
-            assert_equal "sources/watchers_controller.rb", entry.path
-            assert_equal "file", entry.kind
-            assert_equal '0', entry.lastrev.revision
-            assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', entry.lastrev.identifier
-          end
+      end
+      ["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path|
+        ["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
+          entry = @adapter.entry(path, rev)
+          assert_equal "sources/watchers_controller.rb", entry.path
+          assert_equal "file", entry.kind
+          assert_equal '0', entry.lastrev.revision
+          assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', entry.lastrev.identifier
         end
       end
+    end
 
-      def test_locate_on_outdated_repository
-        assert_equal 1, @adapter.entries("images", 0).size
-        assert_equal 2, @adapter.entries("images").size
-        assert_equal 2, @adapter.entries("images", 2).size
-      end
+    def test_locate_on_outdated_repository
+      assert_equal 1, @adapter.entries("images", 0).size
+      assert_equal 2, @adapter.entries("images").size
+      assert_equal 2, @adapter.entries("images", 2).size
+    end
 
-      def test_access_by_nodeid
-        path = 'sources/welcome_controller.rb'
-        assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400bb8672109')
-      end
+    def test_access_by_nodeid
+      path = 'sources/welcome_controller.rb'
+      assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400bb8672109')
+    end
 
-      def test_access_by_fuzzy_nodeid
-        path = 'sources/welcome_controller.rb'
-        # falls back to nodeid
-        assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400')
-      end
+    def test_access_by_fuzzy_nodeid
+      path = 'sources/welcome_controller.rb'
+      # falls back to nodeid
+      assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400')
+    end
 
-      def test_tags
-        assert_equal [@tag_char_1, 'tag_test.00', 'tag-init-revision'], @adapter.tags
-      end
+    def test_tags
+      assert_equal [@tag_char_1, 'tag_test.00', 'tag-init-revision'], @adapter.tags
+    end
 
-      def test_tagmap
-        tm = {
-          @tag_char_1         => 'adf805632193500ad3b615cd04f58f9b0769f576',
-          'tag_test.00'       => '6987191f453a5f6557018d522feea2c450d5588d',
-          'tag-init-revision' => '0885933ad4f68d77c2649cd11f8311276e7ef7ce',
-          }
-        assert_equal tm, @adapter.tagmap
-      end
+    def test_tagmap
+      tm = {
+        @tag_char_1         => 'adf805632193500ad3b615cd04f58f9b0769f576',
+        'tag_test.00'       => '6987191f453a5f6557018d522feea2c450d5588d',
+        'tag-init-revision' => '0885933ad4f68d77c2649cd11f8311276e7ef7ce',
+        }
+      assert_equal tm, @adapter.tagmap
+    end
 
-      def test_branches
-        brs = []
-        @adapter.branches.each do |b|
-          brs << b
-        end
-        assert_equal 7, brs.length
-        assert_equal 'default', brs[0].to_s
-        assert_equal '31', brs[0].revision
-        assert_equal '31eeee7395c8c78e66dd54c50addd078d10b2355', brs[0].scmid
-        assert_equal 'test-branch-01', brs[1].to_s
-        assert_equal '30', brs[1].revision
-        assert_equal 'ad4dc4f80284a4f9168b77e0b6de288e5d207ee7', brs[1].scmid
-        assert_equal @branch_char_1, brs[2].to_s
-        assert_equal '27', brs[2].revision
-        assert_equal '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914', brs[2].scmid
-        assert_equal 'branch (1)[2]&,%.-3_4', brs[3].to_s
-        assert_equal '25', brs[3].revision
-        assert_equal 'afc61e85bde74de930e5846c8451bd55b5bafc9c', brs[3].scmid
-        assert_equal @branch_char_0, brs[4].to_s
-        assert_equal '23', brs[4].revision
-        assert_equal 'c8d3e4887474af6a589190140508037ebaa9d9c3', brs[4].scmid
-        assert_equal 'test_branch.latin-1', brs[5].to_s
-        assert_equal '22', brs[5].revision
-        assert_equal 'c2ffe7da686aa3d956e59f2a2854cf8980a8b768', brs[5].scmid
-        assert_equal 'test-branch-00', brs[6].to_s
-        assert_equal '13', brs[6].revision
-        assert_equal '3a330eb329586ea2adb3f83237c23310e744ebe9', brs[6].scmid
+    def test_branches
+      brs = []
+      @adapter.branches.each do |b|
+        brs << b
       end
+      assert_equal 7, brs.length
+      assert_equal 'default', brs[0].to_s
+      assert_equal '31', brs[0].revision
+      assert_equal '31eeee7395c8c78e66dd54c50addd078d10b2355', brs[0].scmid
+      assert_equal 'test-branch-01', brs[1].to_s
+      assert_equal '30', brs[1].revision
+      assert_equal 'ad4dc4f80284a4f9168b77e0b6de288e5d207ee7', brs[1].scmid
+      assert_equal @branch_char_1, brs[2].to_s
+      assert_equal '27', brs[2].revision
+      assert_equal '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914', brs[2].scmid
+      assert_equal 'branch (1)[2]&,%.-3_4', brs[3].to_s
+      assert_equal '25', brs[3].revision
+      assert_equal 'afc61e85bde74de930e5846c8451bd55b5bafc9c', brs[3].scmid
+      assert_equal @branch_char_0, brs[4].to_s
+      assert_equal '23', brs[4].revision
+      assert_equal 'c8d3e4887474af6a589190140508037ebaa9d9c3', brs[4].scmid
+      assert_equal 'test_branch.latin-1', brs[5].to_s
+      assert_equal '22', brs[5].revision
+      assert_equal 'c2ffe7da686aa3d956e59f2a2854cf8980a8b768', brs[5].scmid
+      assert_equal 'test-branch-00', brs[6].to_s
+      assert_equal '13', brs[6].revision
+      assert_equal '3a330eb329586ea2adb3f83237c23310e744ebe9', brs[6].scmid
+    end
 
-      def test_branchmap
-        bm = {
-           'default'               => '31eeee7395c8c78e66dd54c50addd078d10b2355',
-           'test_branch.latin-1'   => 'c2ffe7da686aa3d956e59f2a2854cf8980a8b768',
-           'branch (1)[2]&,%.-3_4' => 'afc61e85bde74de930e5846c8451bd55b5bafc9c',
-           'test-branch-00'        => '3a330eb329586ea2adb3f83237c23310e744ebe9',
-           "test-branch-01"        => 'ad4dc4f80284a4f9168b77e0b6de288e5d207ee7',
-           @branch_char_0          => 'c8d3e4887474af6a589190140508037ebaa9d9c3',
-           @branch_char_1          => '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914',
-         }
-        assert_equal bm, @adapter.branchmap
-      end
+    def test_branchmap
+      bm = {
+         'default'               => '31eeee7395c8c78e66dd54c50addd078d10b2355',
+         'test_branch.latin-1'   => 'c2ffe7da686aa3d956e59f2a2854cf8980a8b768',
+         'branch (1)[2]&,%.-3_4' => 'afc61e85bde74de930e5846c8451bd55b5bafc9c',
+         'test-branch-00'        => '3a330eb329586ea2adb3f83237c23310e744ebe9',
+         "test-branch-01"        => 'ad4dc4f80284a4f9168b77e0b6de288e5d207ee7',
+         @branch_char_0          => 'c8d3e4887474af6a589190140508037ebaa9d9c3',
+         @branch_char_1          => '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914',
+       }
+      assert_equal bm, @adapter.branchmap
+    end
 
-      def test_path_space
-        p = 'README (1)[2]&,%.-3_4'
-        [15, '933ca60293d7'].each do |r1|
-          assert @adapter.diff(p, r1)
-          assert @adapter.cat(p, r1)
-          assert_equal 1, @adapter.annotate(p, r1).lines.length
-          [25, 'afc61e85bde7'].each do |r2|
-            assert @adapter.diff(p, r1, r2)
-          end
+    def test_path_space
+      p = 'README (1)[2]&,%.-3_4'
+      [15, '933ca60293d7'].each do |r1|
+        assert @adapter.diff(p, r1)
+        assert @adapter.cat(p, r1)
+        assert_equal 1, @adapter.annotate(p, r1).lines.length
+        [25, 'afc61e85bde7'].each do |r2|
+          assert @adapter.diff(p, r1, r2)
         end
       end
+    end
 
-      def test_tag_non_ascii
-        p = "latin-1-dir/test-#{@char_1}-1.txt"
-        assert @adapter.cat(p, @tag_char_1)
-        assert_equal 1, @adapter.annotate(p, @tag_char_1).lines.length
-      end
+    def test_tag_non_ascii
+      p = "latin-1-dir/test-#{@char_1}-1.txt"
+      assert @adapter.cat(p, @tag_char_1)
+      assert_equal 1, @adapter.annotate(p, @tag_char_1).lines.length
+    end
 
-      def test_branch_non_ascii
-        p = "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-1.txt"
-        assert @adapter.cat(p, @branch_char_1)
-        assert_equal 1, @adapter.annotate(p, @branch_char_1).lines.length
-      end
+    def test_branch_non_ascii
+      p = "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-1.txt"
+      assert @adapter.cat(p, @branch_char_1)
+      assert_equal 1, @adapter.annotate(p, @branch_char_1).lines.length
+    end
 
-      def test_nodes_in_branch
-         [
-            'default',
-            @branch_char_1,
-            'branch (1)[2]&,%.-3_4',
-            @branch_char_0,
-            'test_branch.latin-1',
-            'test-branch-00',
-               ].each do |bra|
-          nib0 = @adapter.nodes_in_branch(bra)
-          assert nib0
-          nib1 = @adapter.nodes_in_branch(bra, :limit => 1)
-          assert_equal 1, nib1.size
-          case bra
-            when 'branch (1)[2]&,%.-3_4'
-              if @adapter.class.client_version_above?([1, 6])
-                assert_equal 3, nib0.size
-                assert_equal 'afc61e85bde74de930e5846c8451bd55b5bafc9c', nib0[0]
-                nib2 = @adapter.nodes_in_branch(bra, :limit => 2)
-                assert_equal 2, nib2.size
-                assert_equal '933ca60293d78f7c7979dd123cc0c02431683575', nib2[1]
-              end
-            when @branch_char_1
-              if @adapter.class.client_version_above?([1, 6])
-                assert_equal 2, nib0.size
-                assert_equal '08ff3227303ec0dfcc818efa8e9cc652fe81859f', nib0[1]
-                nib2 = @adapter.nodes_in_branch(bra, :limit => 1)
-                assert_equal 1, nib2.size
-                assert_equal '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914', nib2[0]
-              end
-          end
+    def test_nodes_in_branch
+       [
+          'default',
+          @branch_char_1,
+          'branch (1)[2]&,%.-3_4',
+          @branch_char_0,
+          'test_branch.latin-1',
+          'test-branch-00',
+             ].each do |bra|
+        nib0 = @adapter.nodes_in_branch(bra)
+        assert nib0
+        nib1 = @adapter.nodes_in_branch(bra, :limit => 1)
+        assert_equal 1, nib1.size
+        case bra
+          when 'branch (1)[2]&,%.-3_4'
+            if @adapter.class.client_version_above?([1, 6])
+              assert_equal 3, nib0.size
+              assert_equal 'afc61e85bde74de930e5846c8451bd55b5bafc9c', nib0[0]
+              nib2 = @adapter.nodes_in_branch(bra, :limit => 2)
+              assert_equal 2, nib2.size
+              assert_equal '933ca60293d78f7c7979dd123cc0c02431683575', nib2[1]
+            end
+          when @branch_char_1
+            if @adapter.class.client_version_above?([1, 6])
+              assert_equal 2, nib0.size
+              assert_equal '08ff3227303ec0dfcc818efa8e9cc652fe81859f', nib0[1]
+              nib2 = @adapter.nodes_in_branch(bra, :limit => 1)
+              assert_equal 1, nib2.size
+              assert_equal '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914', nib2[0]
+            end
         end
       end
+    end
 
-      def test_path_encoding_default_utf8
-        adpt1 = Redmine::Scm::Adapters::MercurialAdapter.new(
-                                  REPOSITORY_PATH
-                                )
-        assert_equal "UTF-8", adpt1.path_encoding
-        adpt2 = Redmine::Scm::Adapters::MercurialAdapter.new(
-                                  REPOSITORY_PATH,
-                                  nil,
-                                  nil,
-                                  nil,
-                                  ""
-                                )
-        assert_equal "UTF-8", adpt2.path_encoding
-      end
+    def test_path_encoding_default_utf8
+      adpt1 = Redmine::Scm::Adapters::MercurialAdapter.new(
+                                REPOSITORY_PATH
+                              )
+      assert_equal "UTF-8", adpt1.path_encoding
+      adpt2 = Redmine::Scm::Adapters::MercurialAdapter.new(
+                                REPOSITORY_PATH,
+                                nil,
+                                nil,
+                                nil,
+                                ""
+                              )
+      assert_equal "UTF-8", adpt2.path_encoding
+    end
 
-      private
+    private
 
-      def test_hgversion_for(hgversion, version)
-        @adapter.class.expects(:hgversion_from_command_line).returns(hgversion)
-        assert_equal version, @adapter.class.hgversion
-      end
+    def test_hgversion_for(hgversion, version)
+      @adapter.class.expects(:hgversion_from_command_line).returns(hgversion)
+      assert_equal version, @adapter.class.hgversion
+    end
 
-      def test_template_path_for(version, template)
-        assert_equal "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}",
-                     @adapter.class.template_path_for(version)
-        assert File.exist?(@adapter.class.template_path_for(version))
-      end
-    else
-      puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
+    def test_template_path_for(version, template)
+      assert_equal "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}",
+                   @adapter.class.template_path_for(version)
+      assert File.exist?(@adapter.class.template_path_for(version))
     end
-  end
-rescue LoadError
-  class MercurialMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
+  else
+    puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
+    def test_fake; assert true end
   end
 end
diff --git a/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb
index f272c0a..161f7d2 100644
--- a/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb
+++ b/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb
@@ -17,55 +17,47 @@
 
 require File.expand_path('../../../../../../test_helper', __FILE__)
 
-begin
-  require 'mocha/setup'
+class SubversionAdapterTest < ActiveSupport::TestCase
 
-  class SubversionAdapterTest < ActiveSupport::TestCase
-
-    if repository_configured?('subversion')
-      def setup
-        @adapter = Redmine::Scm::Adapters::SubversionAdapter.new(self.class.subversion_repository_url)
-      end
+  if repository_configured?('subversion')
+    def setup
+      @adapter = Redmine::Scm::Adapters::SubversionAdapter.new(self.class.subversion_repository_url)
+    end
 
-      def test_client_version
-        v = Redmine::Scm::Adapters::SubversionAdapter.client_version
-        assert v.is_a?(Array)
-      end
+    def test_client_version
+      v = Redmine::Scm::Adapters::SubversionAdapter.client_version
+      assert v.is_a?(Array)
+    end
 
-      def test_scm_version
-        to_test = { "svn, version 1.6.13 (r1002816)\n"  => [1,6,13],
-                    "svn, versione 1.6.13 (r1002816)\n" => [1,6,13],
-                    "1.6.1\n1.7\n1.8"                   => [1,6,1],
-                    "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
-        to_test.each do |s, v|
-          test_scm_version_for(s, v)
-        end
+    def test_scm_version
+      to_test = { "svn, version 1.6.13 (r1002816)\n"  => [1,6,13],
+                  "svn, versione 1.6.13 (r1002816)\n" => [1,6,13],
+                  "1.6.1\n1.7\n1.8"                   => [1,6,1],
+                  "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
+      to_test.each do |s, v|
+        test_scm_version_for(s, v)
       end
+    end
 
-      def test_info_not_nil
-        assert_not_nil @adapter.info
-      end
+    def test_info_not_nil
+      assert_not_nil @adapter.info
+    end
 
-      def test_info_nil
-        adpt = Redmine::Scm::Adapters::SubversionAdapter.new(
-                  "file:///invalid/invalid/"
-                  )
-        assert_nil adpt.info
-      end
+    def test_info_nil
+      adpt = Redmine::Scm::Adapters::SubversionAdapter.new(
+                "file:///invalid/invalid/"
+                )
+      assert_nil adpt.info
+    end
 
-      private
+    private
 
-      def test_scm_version_for(scm_version, version)
-        @adapter.class.expects(:scm_version_from_command_line).returns(scm_version)
-        assert_equal version, @adapter.class.svn_binary_version
-      end
-    else
-      puts "Subversion test repository NOT FOUND. Skipping unit tests !!!"
-      def test_fake; assert true end
+    def test_scm_version_for(scm_version, version)
+      @adapter.class.expects(:scm_version_from_command_line).returns(scm_version)
+      assert_equal version, @adapter.class.svn_binary_version
     end
-  end
-rescue LoadError
-  class SubversionMochaFake < ActiveSupport::TestCase
-    def test_fake; assert(false, "Requires mocha to run those tests")  end
+  else
+    puts "Subversion test repository NOT FOUND. Skipping unit tests !!!"
+    def test_fake; assert true end
   end
 end
diff --git a/test/unit/lib/redmine/unified_diff_test.rb b/test/unit/lib/redmine/unified_diff_test.rb
index 4956e52..e3130fd 100644
--- a/test/unit/lib/redmine/unified_diff_test.rb
+++ b/test/unit/lib/redmine/unified_diff_test.rb
@@ -223,8 +223,7 @@ DIFF
 
   def test_utf8_ja
     ja = "  text_tip_issue_end_day: "
-    ja += "\xe3\x81\x93\xe3\x81\xae\xe6\x97\xa5\xe3\x81\xab\xe7\xb5\x82\xe4\xba\x86\xe3\x81\x99\xe3\x82\x8b<span>\xe3\x82\xbf\xe3\x82\xb9\xe3\x82\xaf</span>"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
+    ja += "\xe3\x81\x93\xe3\x81\xae\xe6\x97\xa5\xe3\x81\xab\xe7\xb5\x82\xe4\xba\x86\xe3\x81\x99\xe3\x82\x8b<span>\xe3\x82\xbf\xe3\x82\xb9\xe3\x82\xaf</span>".force_encoding('UTF-8')
     with_settings :repositories_encodings => '' do
       diff = Redmine::UnifiedDiff.new(read_diff_fixture('issue-12641-ja.diff'), :type => 'inline')
       assert_equal 1, diff.size
@@ -234,8 +233,7 @@ DIFF
   end
 
   def test_utf8_ru
-    ru = "        other: "\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbb\xd0\xbe %{count} \xd1\x87\xd0\xb0\xd1\x81<span>\xd0\xb0</span>""
-    ru.force_encoding('UTF-8') if ru.respond_to?(:force_encoding)
+    ru = "        other: "\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbb\xd0\xbe %{count} \xd1\x87\xd0\xb0\xd1\x81<span>\xd0\xb0</span>"".force_encoding('UTF-8')
     with_settings :repositories_encodings => '' do
       diff = Redmine::UnifiedDiff.new(read_diff_fixture('issue-12641-ru.diff'), :type => 'inline')
       assert_equal 1, diff.size
@@ -279,10 +277,8 @@ DIFF
   end
 
   def test_offset_range_japanese_1
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span></span>"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x9e</span>"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
+    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span></span>".force_encoding('UTF-8')
+    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x9e</span>".force_encoding('UTF-8')
     with_settings :repositories_encodings => '' do
       diff = Redmine::UnifiedDiff.new(
                read_diff_fixture('issue-13644-1.diff'), :type => 'sbs')
@@ -294,10 +290,8 @@ DIFF
   end
 
   def test_offset_range_japanese_2
-    ja1 = "<span></span>\xe6\x97\xa5\xe6\x9c\xac"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "<span>\xe3\x81\xab\xe3\x81\xa3\xe3\x81\xbd\xe3\x82\x93</span>\xe6\x97\xa5\xe6\x9c\xac"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
+    ja1 = "<span></span>\xe6\x97\xa5\xe6\x9c\xac".force_encoding('UTF-8')
+    ja2 = "<span>\xe3\x81\xab\xe3\x81\xa3\xe3\x81\xbd\xe3\x82\x93</span>\xe6\x97\xa5\xe6\x9c\xac".force_encoding('UTF-8')
     with_settings :repositories_encodings => '' do
       diff = Redmine::UnifiedDiff.new(
                read_diff_fixture('issue-13644-2.diff'), :type => 'sbs')
@@ -310,10 +304,8 @@ DIFF
 
   def test_offset_range_japanese_3
     # UTF-8 The 1st byte differs.
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe5\xa8\x98</span>"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
+    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>".force_encoding('UTF-8')
+    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe5\xa8\x98</span>".force_encoding('UTF-8')
     with_settings :repositories_encodings => '' do
       diff = Redmine::UnifiedDiff.new(
                read_diff_fixture('issue-13644-3.diff'), :type => 'sbs')
@@ -326,10 +318,8 @@ DIFF
 
   def test_offset_range_japanese_4
     # UTF-8 The 2nd byte differs. 
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
+    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>".force_encoding('UTF-8')
+    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>".force_encoding('UTF-8')
     with_settings :repositories_encodings => '' do
       diff = Redmine::UnifiedDiff.new(
                read_diff_fixture('issue-13644-4.diff'), :type => 'sbs')
@@ -342,10 +332,8 @@ DIFF
 
   def test_offset_range_japanese_5
     # UTF-8 The 2nd byte differs. 
-    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>ok"
-    ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
-    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>ok"
-    ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
+    ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>ok".force_encoding('UTF-8')
+    ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>ok".force_encoding('UTF-8')
     with_settings :repositories_encodings => '' do
       diff = Redmine::UnifiedDiff.new(
                read_diff_fixture('issue-13644-5.diff'), :type => 'sbs')
diff --git a/test/unit/lib/redmine/wiki_formatting/macros_test.rb b/test/unit/lib/redmine/wiki_formatting/macros_test.rb
index 443b6f4..58cc166 100644
--- a/test/unit/lib/redmine/wiki_formatting/macros_test.rb
+++ b/test/unit/lib/redmine/wiki_formatting/macros_test.rb
@@ -207,12 +207,14 @@ class Redmine::WikiFormatting::MacrosTest < ActionView::TestCase
 
   def test_macro_collapse
     text = "{{collapse\n*Collapsed* block of text\n}}"
-    result = textilizable(text)
-
-    assert_select_in result, 'div.collapsed-text'
-    assert_select_in result, 'strong', :text => 'Collapsed'
-    assert_select_in result, 'a.collapsible.collapsed', :text => 'Show'
-    assert_select_in result, 'a.collapsible', :text => 'Hide'
+    with_locale 'en' do
+      result = textilizable(text)
+  
+      assert_select_in result, 'div.collapsed-text'
+      assert_select_in result, 'strong', :text => 'Collapsed'
+      assert_select_in result, 'a.collapsible.collapsed', :text => 'Show'
+      assert_select_in result, 'a.collapsible', :text => 'Hide'
+    end
   end
 
   def test_macro_collapse_with_one_arg
diff --git a/test/unit/mail_handler_test.rb b/test/unit/mail_handler_test.rb
index 86f286e..7d484b4 100644
--- a/test/unit/mail_handler_test.rb
+++ b/test/unit/mail_handler_test.rb
@@ -67,6 +67,7 @@ class MailHandlerTest < ActiveSupport::TestCase
     # Email notification should be sent
     mail = ActionMailer::Base.deliveries.last
     assert_not_nil mail
+    assert mail.subject.include?("##{issue.id}")
     assert mail.subject.include?('New ticket on a given project')
   end
 
@@ -410,8 +411,7 @@ class MailHandlerTest < ActiveSupport::TestCase
   end
 
   def test_add_issue_with_japanese_keywords
-    ja_dev = "\xe9\x96\x8b\xe7\x99\xba"
-    ja_dev.force_encoding('UTF-8') if ja_dev.respond_to?(:force_encoding)
+    ja_dev = "\xe9\x96\x8b\xe7\x99\xba".force_encoding('UTF-8')
     tracker = Tracker.create!(:name => ja_dev)
     Project.find(1).trackers << tracker
     issue = submit_email(
@@ -446,8 +446,7 @@ class MailHandlerTest < ActiveSupport::TestCase
             )
     assert_kind_of Issue, issue
     assert_equal 1, issue.attachments.size
-    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
+    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8')
     attachment = issue.attachments.first
     assert_equal ja, attachment.filename
     assert_equal 5, attachment.filesize
@@ -463,8 +462,7 @@ class MailHandlerTest < ActiveSupport::TestCase
             )
     assert_kind_of Issue, issue
     assert_equal 1, issue.attachments.size
-    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
+    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8')
     attachment = issue.attachments.first
     assert_equal ja, attachment.filename
     assert_equal 5, attachment.filesize
@@ -480,10 +478,8 @@ class MailHandlerTest < ActiveSupport::TestCase
             )
     assert_kind_of Issue, issue
     assert_equal 1, issue.attachments.size
-    u = ""
-    u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
-    u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
-    u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
+    u = "".force_encoding('UTF-8')
+    u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8')
     11.times { u << u1 }
     attachment = issue.attachments.first
     assert_equal "#{u}.png", attachment.filename
@@ -500,10 +496,8 @@ class MailHandlerTest < ActiveSupport::TestCase
             )
     assert_kind_of Issue, issue
     assert_equal 1, issue.attachments.size
-    u = ""
-    u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
-    u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
-    u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
+    u = "".force_encoding('UTF-8')
+    u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8')
     11.times { u << u1 }
     attachment = issue.attachments.first
     assert_equal "#{u}.txt", attachment.filename
@@ -533,38 +527,51 @@ class MailHandlerTest < ActiveSupport::TestCase
               'subject_as_iso-8859-1.eml',
               :issue => {:project => 'ecookbook'}
             )
-    str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc..."
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc...".force_encoding('UTF-8')
     assert_kind_of Issue, issue
     assert_equal str, issue.subject
   end
 
+  def test_quoted_printable_utf8
+    issue = submit_email(
+              'quoted_printable_utf8.eml',
+              :issue => {:project => 'ecookbook'}
+            )
+    assert_kind_of Issue, issue
+    str = "Freundliche Gr\xc3\xbcsse".force_encoding('UTF-8')
+    assert_equal str, issue.description
+  end
+
+  def test_gmail_iso8859_2
+    issue = submit_email(
+              'gmail-iso8859-2.eml',
+              :issue => {:project => 'ecookbook'}
+            )
+    assert_kind_of Issue, issue
+    str = "Na \xc5\xa1triku se su\xc5\xa1i \xc5\xa1osi\xc4\x87.".force_encoding('UTF-8')
+    assert issue.description.include?(str)
+  end
+
   def test_add_issue_with_japanese_subject
     issue = submit_email(
               'subject_japanese_1.eml',
               :issue => {:project => 'ecookbook'}
             )
     assert_kind_of Issue, issue
-    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
+    ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8')
     assert_equal ja, issue.subject
   end
 
   def test_add_issue_with_korean_body
     # Make sure mail bodies with a charset unknown to Ruby
     # but known to the Mail gem 2.5.4 are handled correctly
-    kr = "\xEA\xB3\xA0\xEB\xA7\x99\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4."
-    if !kr.respond_to?(:force_encoding)
-      puts "\nOn Ruby 1.8, skip Korean encoding mail body test"
-    else
-      kr.force_encoding('UTF-8')
-      issue = submit_email(
-              'body_ks_c_5601-1987.eml',
-              :issue => {:project => 'ecookbook'}
-            )
-      assert_kind_of Issue, issue
-      assert_equal kr, issue.description
-    end
+    kr = "\xEA\xB3\xA0\xEB\xA7\x99\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4.".force_encoding('UTF-8')
+    issue = submit_email(
+            'body_ks_c_5601-1987.eml',
+            :issue => {:project => 'ecookbook'}
+          )
+    assert_kind_of Issue, issue
+    assert_equal kr, issue.description
   end
 
   def test_add_issue_with_no_subject_header
@@ -582,8 +589,7 @@ class MailHandlerTest < ActiveSupport::TestCase
               :issue => {:project => 'ecookbook'}
             )
     assert_kind_of Issue, issue
-    ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
-    ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
+    ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8')
     assert_equal ja, issue.subject
   end
 
@@ -625,6 +631,19 @@ class MailHandlerTest < ActiveSupport::TestCase
     end
   end
 
+  test "should not ignore Auto-Submitted headers not defined in RFC3834" do
+    [
+      "Auto-Submitted: auto-forwarded"
+    ].each do |header|
+      raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
+      raw = header + "\n" + raw
+
+      assert_difference 'Issue.count', 1 do
+        assert_not_nil MailHandler.receive(raw), "email with #{header} header was ignored"
+      end
+    end
+  end
+
   def test_add_issue_should_send_email_notification
     Setting.notified_events = ['issue_added']
     ActionMailer::Base.deliveries.clear
@@ -860,10 +879,8 @@ class MailHandlerTest < ActiveSupport::TestCase
     end
     user = User.order('id DESC').first
     assert_equal "foo at example.org", user.mail
-    str1 = "\xc3\x84\xc3\xa4"
-    str2 = "\xc3\x96\xc3\xb6"
-    str1.force_encoding('UTF-8') if str1.respond_to?(:force_encoding)
-    str2.force_encoding('UTF-8') if str2.respond_to?(:force_encoding)
+    str1 = "\xc3\x84\xc3\xa4".force_encoding('UTF-8')
+    str2 = "\xc3\x96\xc3\xb6".force_encoding('UTF-8')
     assert_equal str1, user.firstname
     assert_equal str2, user.lastname
   end
diff --git a/test/unit/mailer_test.rb b/test/unit/mailer_test.rb
index 983e9fc..b3678eb 100644
--- a/test/unit/mailer_test.rb
+++ b/test/unit/mailer_test.rb
@@ -34,6 +34,7 @@ class MailerTest < ActiveSupport::TestCase
     Setting.host_name = 'mydomain.foo'
     Setting.protocol = 'http'
     Setting.plain_text_mail = '0'
+    User.current = nil
   end
 
   def test_generated_links_in_emails
diff --git a/test/unit/member_test.rb b/test/unit/member_test.rb
index 6ba9717..481eca6 100644
--- a/test/unit/member_test.rb
+++ b/test/unit/member_test.rb
@@ -79,9 +79,8 @@ class MemberTest < ActiveSupport::TestCase
     member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [])
     assert !member.save
     assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
-    str = "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
-    assert_equal str, [member.errors.full_messages].flatten.join
+    assert_equal "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8'),
+    	[member.errors.full_messages].flatten.join
   end
 
   def test_validate_member_role
@@ -121,7 +120,7 @@ class MemberTest < ActiveSupport::TestCase
     end
     assert m.destroyed?
   ensure
-    Member._destroy_callbacks.reject! {|c| c.filter==:destroy_test_callback}
+    Member._destroy_callbacks.delete(:destroy_test_callback)
   end
 
   def test_sort_without_roles
diff --git a/test/unit/principal_test.rb b/test/unit/principal_test.rb
index 2ddcc8b..fb5917f 100644
--- a/test/unit/principal_test.rb
+++ b/test/unit/principal_test.rb
@@ -23,7 +23,7 @@ class PrincipalTest < ActiveSupport::TestCase
   fixtures :users, :projects, :members, :member_roles
 
   def test_active_scope_should_return_groups_and_active_users
-    result = Principal.active.all
+    result = Principal.active.to_a
     assert_include Group.first, result
     assert_not_nil result.detect {|p| p.is_a?(User)}
     assert_nil result.detect {|p| p.is_a?(User) && !p.active?}
@@ -56,7 +56,7 @@ class PrincipalTest < ActiveSupport::TestCase
 
   def test_sorted_scope_should_sort_users_before_groups
     scope = Principal.where("type <> ?", 'AnonymousUser')
-    expected_order = scope.all.sort do |a, b|
+    expected_order = scope.to_a.sort do |a, b|
       if a.is_a?(User) && b.is_a?(Group)
         -1
       elsif a.is_a?(Group) && b.is_a?(User)
diff --git a/test/unit/project_nested_set_test.rb b/test/unit/project_nested_set_test.rb
index c603acb..713c7b1 100644
--- a/test/unit/project_nested_set_test.rb
+++ b/test/unit/project_nested_set_test.rb
@@ -63,6 +63,11 @@ class ProjectNestedSetTest < ActiveSupport::TestCase
     assert_valid_nested_set
   end
 
+  def test_rebuild_without_projects_should_not_fail
+    Project.delete_all
+    assert Project.rebuild_tree!
+  end
+
   def test_moving_a_child_to_a_different_parent_should_keep_valid_tree
     assert_no_difference 'Project.count' do
       Project.find_by_name('B1').set_parent!(Project.find_by_name('A2'))
@@ -176,7 +181,7 @@ class ProjectNestedSetTest < ActiveSupport::TestCase
     projects.each do |project|
       if project.children.any?
         # sibling projects sorted alphabetically
-        assert_equal project.children.map(&:name).sort, project.children.order('lft').map(&:name), "Project #{project.name}'s children were not properly sorted"
+        assert_equal project.children.map(&:name).sort, project.children.sort_by(&:lft).map(&:name), "Project #{project.name}'s children were not properly sorted"
       end
     end
   end
diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb
index 0dc3a54..46c25a8 100644
--- a/test/unit/project_test.rb
+++ b/test/unit/project_test.rb
@@ -316,7 +316,7 @@ class ProjectTest < ActiveSupport::TestCase
 
     parent.reload
     assert_equal 4, parent.children.size
-    assert_equal parent.children.all.sort_by(&:name), parent.children.all
+    assert_equal parent.children.sort_by(&:name), parent.children.to_a
   end
 
   def test_set_parent_should_update_issue_fixed_version_associations_when_a_fixed_version_is_moved_out_of_the_hierarchy
@@ -729,7 +729,7 @@ class ProjectTest < ActiveSupport::TestCase
 
   def test_activities_should_use_the_system_activities
     project = Project.find(1)
-    assert_equal project.activities, TimeEntryActivity.where(:active => true).all
+    assert_equal project.activities.to_a, TimeEntryActivity.where(:active => true).to_a
     assert_kind_of ActiveRecord::Relation, project.activities
   end
 
diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb
index 084e91a..190c0e4 100644
--- a/test/unit/query_test.rb
+++ b/test/unit/query_test.rb
@@ -101,9 +101,9 @@ class QueryTest < ActiveSupport::TestCase
   end
 
   def find_issues_with_query(query)
-    Issue.includes([:assigned_to, :status, :tracker, :project, :priority]).where(
+    Issue.joins(:status, :tracker, :project, :priority).where(
          query.statement
-       ).all
+       ).references([:assigned_to, :status, :tracker, :project, :priority]).to_a
   end
 
   def assert_find_issues_with_query_is_successful(query)
@@ -1118,9 +1118,7 @@ class QueryTest < ActiveSupport::TestCase
   def test_label_for_fr
     set_language_if_valid 'fr'
     q = IssueQuery.new
-    s = "Assign\xc3\xa9 \xc3\xa0"
-    s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
-    assert_equal s, q.label_for('assigned_to_id')
+    assert_equal "Assign\xc3\xa9 \xc3\xa0".force_encoding('UTF-8'), q.label_for('assigned_to_id')
   end
 
   def test_editable_by
diff --git a/test/unit/repository_bazaar_test.rb b/test/unit/repository_bazaar_test.rb
index 3e15958..6fae0b9 100644
--- a/test/unit/repository_bazaar_test.rb
+++ b/test/unit/repository_bazaar_test.rb
@@ -42,11 +42,10 @@ class RepositoryBazaarTest < ActiveSupport::TestCase
   # you cannot run Bazaar non ASCII path tests.
   #
   RUN_LATIN1_OUTPUT_TEST = (RUBY_PLATFORM != 'java' &&
-                             REPOSITORY_PATH.respond_to?(:force_encoding) &&
                              Encoding.locale_charmap == "ISO-8859-1")
 
-  CHAR_1_UTF8_HEX   = "\xc3\x9c"
-  CHAR_1_LATIN1_HEX = "\xdc"
+  CHAR_1_UTF8_HEX   = "\xc3\x9c".force_encoding('UTF-8')
+  CHAR_1_LATIN1_HEX = "\xdc".force_encoding('ASCII-8BIT')
 
   def setup
     @project = Project.find(3)
@@ -54,12 +53,6 @@ class RepositoryBazaarTest < ActiveSupport::TestCase
               :project => @project, :url => REPOSITORY_PATH_TRUNK,
               :log_encoding => 'UTF-8')
     assert @repository
-    @char_1_utf8      = CHAR_1_UTF8_HEX.dup
-    @char_1_ascii8bit = CHAR_1_LATIN1_HEX.dup
-    if @char_1_utf8.respond_to?(:force_encoding)
-      @char_1_utf8.force_encoding('UTF-8')
-      @char_1_ascii8bit.force_encoding('ASCII-8BIT')
-    end
   end
 
   def test_blank_path_to_repository_error_message
@@ -76,8 +69,7 @@ class RepositoryBazaarTest < ActiveSupport::TestCase
 
   def test_blank_path_to_repository_error_message_fr
     set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Bazaar.new(
                           :project      => @project,
                           :url          => "",
@@ -178,70 +170,70 @@ class RepositoryBazaarTest < ActiveSupport::TestCase
       def test_cat_latin1_path
         latin1_repo = create_latin1_repo
         buf = latin1_repo.cat(
-                 "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", 2)
+                 "test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-2.txt", 2)
         assert buf
         lines = buf.split("\n")
         assert_equal 2, lines.length
         assert_equal 'It is written in Python.', lines[1]
 
         buf = latin1_repo.cat(
-                 "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", 2)
+                 "test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt", 2)
         assert buf
         lines = buf.split("\n")
         assert_equal 1, lines.length
-        assert_equal "test-#{@char_1_ascii8bit}.txt", lines[0]
+        assert_equal "test-#{CHAR_1_LATIN1_HEX}.txt", lines[0]
       end
 
       def test_annotate_latin1_path
         latin1_repo = create_latin1_repo
         ann1 = latin1_repo.annotate(
-                   "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", 2)
+                   "test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-2.txt", 2)
         assert_equal 2, ann1.lines.size
         assert_equal '2', ann1.revisions[0].identifier
         assert_equal 'test00@', ann1.revisions[0].author
         assert_equal 'It is written in Python.', ann1.lines[1]
         ann2 = latin1_repo.annotate(
-                   "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", 2)
+                   "test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt", 2)
         assert_equal 1, ann2.lines.size
         assert_equal '2', ann2.revisions[0].identifier
         assert_equal 'test00@', ann2.revisions[0].author
-        assert_equal "test-#{@char_1_ascii8bit}.txt", ann2.lines[0]
+        assert_equal "test-#{CHAR_1_LATIN1_HEX}.txt", ann2.lines[0]
       end
 
       def test_diff_latin1_path
         latin1_repo = create_latin1_repo
         diff1 = latin1_repo.diff(
-                  "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", 2, 1)
+                  "test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt", 2, 1)
         assert_equal 7, diff1.size
         buf =  diff1[5].gsub(/\r\n|\r|\n/, "")
-        assert_equal "+test-#{@char_1_ascii8bit}.txt", buf
+        assert_equal "+test-#{CHAR_1_LATIN1_HEX}.txt", buf
       end
 
       def test_entries_latin1_path
         latin1_repo = create_latin1_repo
-        entries = latin1_repo.entries("test-#{@char_1_utf8}-dir", 2)
+        entries = latin1_repo.entries("test-#{CHAR_1_UTF8_HEX}-dir", 2)
         assert_kind_of Redmine::Scm::Adapters::Entries, entries
         assert_equal 3, entries.size
         assert_equal 'file', entries[1].kind
-        assert_equal "test-#{@char_1_utf8}-1.txt", entries[0].name
-        assert_equal "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", entries[0].path
+        assert_equal "test-#{CHAR_1_UTF8_HEX}-1.txt", entries[0].name
+        assert_equal "test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt", entries[0].path
       end
 
       def test_entry_latin1_path
         latin1_repo = create_latin1_repo
-        ["test-#{@char_1_utf8}-dir",
-          "/test-#{@char_1_utf8}-dir",
-          "/test-#{@char_1_utf8}-dir/"
+        ["test-#{CHAR_1_UTF8_HEX}-dir",
+          "/test-#{CHAR_1_UTF8_HEX}-dir",
+          "/test-#{CHAR_1_UTF8_HEX}-dir/"
         ].each do |path|
           entry = latin1_repo.entry(path, 2)
-          assert_equal "test-#{@char_1_utf8}-dir", entry.path
+          assert_equal "test-#{CHAR_1_UTF8_HEX}-dir", entry.path
           assert_equal "dir", entry.kind
         end
-        ["test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt",
-          "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt"
+        ["test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt",
+          "/test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt"
         ].each do |path|
           entry = latin1_repo.entry(path, 2)
-          assert_equal "test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt",
+          assert_equal "test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt",
                        entry.path
           assert_equal "file", entry.kind
         end
@@ -256,35 +248,33 @@ class RepositoryBazaarTest < ActiveSupport::TestCase
 
         cs2 = latin1_repo.changesets.find_by_revision('2')
         assert_not_nil cs2
-        assert_equal "test-#{@char_1_utf8}", cs2.comments
+        assert_equal "test-#{CHAR_1_UTF8_HEX}", cs2.comments
         c2  = cs2.filechanges.sort_by(&:path)
         assert_equal 4, c2.size
         assert_equal 'A', c2[0].action
-        assert_equal "/test-#{@char_1_utf8}-dir/", c2[0].path
+        assert_equal "/test-#{CHAR_1_UTF8_HEX}-dir/", c2[0].path
         assert_equal 'A', c2[1].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-1.txt", c2[1].path
+        assert_equal "/test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-1.txt", c2[1].path
         assert_equal 'A', c2[2].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", c2[2].path
+        assert_equal "/test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-2.txt", c2[2].path
         assert_equal 'A', c2[3].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}.txt", c2[3].path
+        assert_equal "/test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}.txt", c2[3].path
 
         cs3 = latin1_repo.changesets.find_by_revision('3')
         assert_not_nil cs3
-        assert_equal "modify, move and delete #{@char_1_utf8} files", cs3.comments
+        assert_equal "modify, move and delete #{CHAR_1_UTF8_HEX} files", cs3.comments
         c3  = cs3.filechanges.sort_by(&:path)
         assert_equal 3, c3.size
         assert_equal 'M', c3[0].action
-        assert_equal "/test-#{@char_1_utf8}-1.txt", c3[0].path
+        assert_equal "/test-#{CHAR_1_UTF8_HEX}-1.txt", c3[0].path
         assert_equal 'D', c3[1].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}-2.txt", c3[1].path
+        assert_equal "/test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}-2.txt", c3[1].path
         assert_equal 'M', c3[2].action
-        assert_equal "/test-#{@char_1_utf8}-dir/test-#{@char_1_utf8}.txt", c3[2].path
+        assert_equal "/test-#{CHAR_1_UTF8_HEX}-dir/test-#{CHAR_1_UTF8_HEX}.txt", c3[2].path
       end
     else
-      msg = "Bazaar non ASCII output test cannot run this environment." + "\n"
-      if msg.respond_to?(:force_encoding)
-        msg += "Encoding.locale_charmap: " + Encoding.locale_charmap + "\n"
-      end
+      msg = "Bazaar non ASCII output test cannot run this environment.\n"
+      msg += "Encoding.locale_charmap: " + Encoding.locale_charmap + "\n"
       puts msg
     end
 
diff --git a/test/unit/repository_cvs_test.rb b/test/unit/repository_cvs_test.rb
index 223b8ec..dcce5ed 100644
--- a/test/unit/repository_cvs_test.rb
+++ b/test/unit/repository_cvs_test.rb
@@ -52,8 +52,7 @@ class RepositoryCvsTest < ActiveSupport::TestCase
 
   def test_blank_module_error_message_fr
     set_language_if_valid 'fr'
-    str = "Module doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Module doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Cvs.new(
                           :project       => @project,
                           :identifier    => 'test',
@@ -81,8 +80,7 @@ class RepositoryCvsTest < ActiveSupport::TestCase
 
   def test_blank_cvsroot_error_message_fr
     set_language_if_valid 'fr'
-    str = "CVSROOT doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "CVSROOT doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Cvs.new(
                           :project       => @project,
                           :identifier    => 'test',
diff --git a/test/unit/repository_darcs_test.rb b/test/unit/repository_darcs_test.rb
index 255fcaf..9e98b0f 100644
--- a/test/unit/repository_darcs_test.rb
+++ b/test/unit/repository_darcs_test.rb
@@ -49,8 +49,7 @@ class RepositoryDarcsTest < ActiveSupport::TestCase
 
   def test_blank_path_to_repository_error_message_fr
     set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Darcs.new(
                           :project      => @project,
                           :url          => "",
diff --git a/test/unit/repository_filesystem_test.rb b/test/unit/repository_filesystem_test.rb
index 1a4dfc7..dd65465 100644
--- a/test/unit/repository_filesystem_test.rb
+++ b/test/unit/repository_filesystem_test.rb
@@ -47,8 +47,7 @@ class RepositoryFilesystemTest < ActiveSupport::TestCase
 
   def test_blank_root_directory_error_message_fr
     set_language_if_valid 'fr'
-    str = "R\xc3\xa9pertoire racine doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "R\xc3\xa9pertoire racine doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Filesystem.new(
                           :project      => @project,
                           :url          => "",
diff --git a/test/unit/repository_git_test.rb b/test/unit/repository_git_test.rb
index 4382f61..94e5747 100644
--- a/test/unit/repository_git_test.rb
+++ b/test/unit/repository_git_test.rb
@@ -28,8 +28,8 @@ class RepositoryGitTest < ActiveSupport::TestCase
   NUM_REV = 28
   NUM_HEAD = 6
 
-  FELIX_HEX  = "Felix Sch\xC3\xA4fer"
-  CHAR_1_HEX = "\xc3\x9c"
+  FELIX_HEX  = "Felix Sch\xC3\xA4fer".force_encoding('UTF-8')
+  CHAR_1_HEX = "\xc3\x9c".force_encoding('UTF-8')
 
   ## Git, Mercurial and CVS path encodings are binary.
   ## Subversion supports URL encoding for path.
@@ -47,10 +47,6 @@ class RepositoryGitTest < ActiveSupport::TestCase
                         :path_encoding => 'ISO-8859-1'
                         )
     assert @repository
-    @char_1        = CHAR_1_HEX.dup
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-    end
   end
 
   def test_blank_path_to_repository_error_message
@@ -66,8 +62,7 @@ class RepositoryGitTest < ActiveSupport::TestCase
 
   def test_blank_path_to_repository_error_message_fr
     set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Git.new(
                           :project      => @project,
                           :url          => "",
@@ -118,7 +113,7 @@ class RepositoryGitTest < ActiveSupport::TestCase
       assert_equal "jsmith <jsmith at 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 Time.gm(2007, 12, 14, 9, 22, 52), commit.committed_on
       assert_equal "2007-12-14".to_date, commit.commit_date
       assert_equal 3, commit.filechanges.count
       change = commit.filechanges.sort_by(&:path).first
@@ -450,14 +445,14 @@ class RepositoryGitTest < ActiveSupport::TestCase
       else
         # latin-1 encoding path
         changesets = @repository.latest_changesets(
-                      "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89')
+                      "latin-1-dir/test-#{CHAR_1_HEX}-2.txt", '64f1f3e89')
         assert_equal [
               '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
               '4fc55c43bf3d3dc2efb66145365ddc17639ce81e',
           ], changesets.collect(&:revision)
 
         changesets = @repository.latest_changesets(
-                    "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89', 1)
+                    "latin-1-dir/test-#{CHAR_1_HEX}-2.txt", '64f1f3e89', 1)
         assert_equal [
               '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
           ], changesets.collect(&:revision)
@@ -475,7 +470,7 @@ class RepositoryGitTest < ActiveSupport::TestCase
         @project.reload
         assert_equal NUM_REV, @repository.changesets.count
         changesets = @repository.latest_changesets(
-                    "latin-1-dir/test-#{@char_1}-subdir", '1ca7f5ed')
+                    "latin-1-dir/test-#{CHAR_1_HEX}-subdir", '1ca7f5ed')
         assert_equal [
               '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127',
           ], changesets.collect(&:revision)
@@ -538,13 +533,9 @@ class RepositoryGitTest < ActiveSupport::TestCase
       @repository.fetch_changesets
       @project.reload
       assert_equal NUM_REV, @repository.changesets.count
-      str_felix_hex  = FELIX_HEX.dup
-      if str_felix_hex.respond_to?(:force_encoding)
-          str_felix_hex.force_encoding('UTF-8')
-      end
       c = @repository.changesets.find_by_revision(
                         'ed5bb786bbda2dee66a2d50faf51429dbc043a7b')
-      assert_equal "#{str_felix_hex} <felix at fachschaften.org>", c.committer
+      assert_equal "#{FELIX_HEX} <felix at fachschaften.org>", c.committer
     end
 
     def test_previous
diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb
index 9762e47..0518055 100644
--- a/test/unit/repository_mercurial_test.rb
+++ b/test/unit/repository_mercurial_test.rb
@@ -24,7 +24,9 @@ class RepositoryMercurialTest < ActiveSupport::TestCase
 
   REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
   NUM_REV = 34
-  CHAR_1_HEX = "\xc3\x9c"
+
+  CHAR_1_HEX = "\xc3\x9c".force_encoding('UTF-8')
+  BRANCH_CHAR_1 = "branch-#{CHAR_1_HEX}-01".force_encoding('UTF-8')
 
   def setup
     @project    = Project.find(3)
@@ -34,16 +36,6 @@ class RepositoryMercurialTest < ActiveSupport::TestCase
                       :path_encoding => 'ISO-8859-1'
                       )
     assert @repository
-    @char_1        = CHAR_1_HEX.dup
-    @tag_char_1    = "tag-#{CHAR_1_HEX}-00"
-    @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
-    @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
-    if @char_1.respond_to?(:force_encoding)
-      @char_1.force_encoding('UTF-8')
-      @tag_char_1.force_encoding('UTF-8')
-      @branch_char_0.force_encoding('UTF-8')
-      @branch_char_1.force_encoding('UTF-8')
-    end
   end
 
   def test_blank_path_to_repository_error_message
@@ -59,8 +51,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase
 
   def test_blank_path_to_repository_error_message_fr
     set_language_if_valid 'fr'
-    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Mercurial.new(
                           :project      => @project,
                           :url          => "",
@@ -362,11 +353,11 @@ class RepositoryMercurialTest < ActiveSupport::TestCase
       assert_equal NUM_REV, @repository.changesets.count
 
       if @repository.scm.class.client_version_above?([1, 6])
-        changesets = @repository.latest_changesets('', @branch_char_1)
+        changesets = @repository.latest_changesets('', BRANCH_CHAR_1)
         assert_equal %w|27 26|, changesets.collect(&:revision)
       end
 
-      changesets = @repository.latest_changesets("latin-1-dir/test-#{@char_1}-subdir", @branch_char_1)
+      changesets = @repository.latest_changesets("latin-1-dir/test-#{CHAR_1_HEX}-subdir", BRANCH_CHAR_1)
       assert_equal %w|27|, changesets.collect(&:revision)
     end
 
@@ -429,8 +420,8 @@ class RepositoryMercurialTest < ActiveSupport::TestCase
       scmid3 = scmid_for_assert(hex3, is_short_scmid)
       assert_equal 1, c3.size
       assert_equal 'A', c3[0].action
-      assert_equal "/latin-1-dir/test-#{@char_1}-1.txt",  c3[0].path
-      assert_equal "/latin-1-dir/test-#{@char_1}.txt",    c3[0].from_path
+      assert_equal "/latin-1-dir/test-#{CHAR_1_HEX}-1.txt",  c3[0].path
+      assert_equal "/latin-1-dir/test-#{CHAR_1_HEX}.txt",    c3[0].from_path
       assert_equal scmid3, c3[0].from_revision
     end
     private :assert_copied_files
diff --git a/test/unit/repository_subversion_test.rb b/test/unit/repository_subversion_test.rb
index d9b9a15..2fe50da 100644
--- a/test/unit/repository_subversion_test.rb
+++ b/test/unit/repository_subversion_test.rb
@@ -202,13 +202,7 @@ class RepositorySubversionTest < ActiveSupport::TestCase
 
     def test_log_encoding_ignore_setting
       with_settings :commit_logs_encoding => 'windows-1252' do
-        s1 = "\xC2\x80"
-        s2 = "\xc3\x82\xc2\x80"
-        if s1.respond_to?(:force_encoding)
-          s1.force_encoding('ISO-8859-1')
-          s2.force_encoding('UTF-8')
-          assert_equal s1.encode('UTF-8'), s2
-        end
+        s2 = "\xc3\x82\xc2\x80".force_encoding('UTF-8')
         c = Changeset.new(:repository => @repository,
                           :comments   => s2,
                           :revision   => '123',
diff --git a/test/unit/repository_test.rb b/test/unit/repository_test.rb
index 8d2e786..d2565e9 100644
--- a/test/unit/repository_test.rb
+++ b/test/unit/repository_test.rb
@@ -54,8 +54,7 @@ class RepositoryTest < ActiveSupport::TestCase
 
   def test_blank_log_encoding_error_message_fr
     set_language_if_valid 'fr'
-    str = "Encodage des messages de commit doit \xc3\xaatre renseign\xc3\xa9(e)"
-    str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
+    str = "Encodage des messages de commit doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
     repo = Repository::Bazaar.new(
                         :project      => Project.find(3),
                         :url          => "/test"
@@ -175,7 +174,7 @@ class RepositoryTest < ActiveSupport::TestCase
 
   def test_destroy_should_delete_parents_associations
     changeset = Changeset.find(102)
-    changeset.parents = Changeset.where(:id => [100, 101]).all
+    changeset.parents = Changeset.where(:id => [100, 101]).to_a
     assert_difference 'Changeset.connection.select_all("select * from changeset_parents").count', -2 do
       Repository.find(10).destroy
     end
@@ -183,7 +182,7 @@ class RepositoryTest < ActiveSupport::TestCase
 
   def test_destroy_should_delete_issues_associations
     changeset = Changeset.find(102)
-    changeset.issues = Issue.where(:id => [1, 2]).all
+    changeset.issues = Issue.where(:id => [1, 2]).to_a
     assert_difference 'Changeset.connection.select_all("select * from changesets_issues").count', -2 do
       Repository.find(10).destroy
     end
diff --git a/test/unit/role_test.rb b/test/unit/role_test.rb
index 710120d..e1ba993 100644
--- a/test/unit/role_test.rb
+++ b/test/unit/role_test.rb
@@ -21,16 +21,16 @@ class RoleTest < ActiveSupport::TestCase
   fixtures :roles, :workflows, :trackers
 
   def test_sorted_scope
-    assert_equal Role.all.sort, Role.sorted.all
+    assert_equal Role.all.sort, Role.sorted.to_a
   end
 
   def test_givable_scope
-    assert_equal Role.all.reject(&:builtin?).sort, Role.givable.all
+    assert_equal Role.all.reject(&:builtin?).sort, Role.givable.to_a
   end
 
   def test_builtin_scope
-    assert_equal Role.all.select(&:builtin?).sort, Role.builtin(true).all.sort
-    assert_equal Role.all.reject(&:builtin?).sort, Role.builtin(false).all.sort
+    assert_equal Role.all.select(&:builtin?).sort, Role.builtin(true).to_a.sort
+    assert_equal Role.all.reject(&:builtin?).sort, Role.builtin(false).to_a.sort
   end
 
   def test_copy_from
diff --git a/test/unit/tracker_test.rb b/test/unit/tracker_test.rb
index 64f1078..70d892b 100644
--- a/test/unit/tracker_test.rb
+++ b/test/unit/tracker_test.rb
@@ -21,7 +21,7 @@ class TrackerTest < ActiveSupport::TestCase
   fixtures :trackers, :workflows, :issue_statuses, :roles, :issues
 
   def test_sorted_scope
-    assert_equal Tracker.all.sort, Tracker.sorted.all
+    assert_equal Tracker.all.sort, Tracker.sorted.to_a
   end
 
   def test_named_scope
diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb
index aa930a7..49f1cbd 100644
--- a/test/unit/user_test.rb
+++ b/test/unit/user_test.rb
@@ -34,8 +34,9 @@ class UserTest < ActiveSupport::TestCase
   end
 
   def test_sorted_scope_should_sort_user_by_display_name
-    assert_equal User.all.map(&:name).map(&:downcase).sort,
-                 User.sorted.map(&:name).map(&:downcase)
+    # Use .active to ignore anonymous with localized display name
+    assert_equal User.active.map(&:name).map(&:downcase).sort,
+                 User.active.sorted.map(&:name).map(&:downcase)
   end
 
   def test_generate
@@ -995,10 +996,10 @@ class UserTest < ActiveSupport::TestCase
       end
 
       should "return true only if user has permission on all these projects" do
-        assert_equal true, @admin.allowed_to?(:view_project, Project.all)
-        assert_equal false, @dlopper.allowed_to?(:view_project, Project.all) #cannot see Project(2)
-        assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects) #Manager or Developer everywhere
-        assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects) #Dev cannot delete_issue_watchers
+        assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
+        assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
+        assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
+        assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
       end
 
       should "behave correctly with arrays of 1 project" do
diff --git a/test/unit/version_test.rb b/test/unit/version_test.rb
index ea91476..a1dddd9 100644
--- a/test/unit/version_test.rb
+++ b/test/unit/version_test.rb
@@ -93,7 +93,7 @@ class VersionTest < ActiveSupport::TestCase
     assert_progress_equal (100.0)/3, v.closed_percent
   end
 
-  def test_progress_should_consider_estimated_hours_to_weigth_issues
+  def test_progress_should_consider_estimated_hours_to_weight_issues
     project = Project.find(1)
     v = Version.create!(:project => project, :name => 'Progress')
     add_issue(v, :estimated_hours => 10)
@@ -104,7 +104,7 @@ class VersionTest < ActiveSupport::TestCase
     assert_progress_equal 25.0/95.0*100, v.closed_percent
   end
 
-  def test_progress_should_consider_average_estimated_hours_to_weigth_unestimated_issues
+  def test_progress_should_consider_average_estimated_hours_to_weight_unestimated_issues
     project = Project.find(1)
     v = Version.create!(:project => project, :name => 'Progress')
     add_issue(v, :done_ratio => 20)
@@ -124,7 +124,7 @@ class VersionTest < ActiveSupport::TestCase
     v5 = Version.create!(:project_id => 1, :name => 'v5', :effective_date => '2012-07-02')
 
     assert_equal [v5, v3, v1, v2, v4], [v1, v2, v3, v4, v5].sort
-    assert_equal [v5, v3, v1, v2, v4], Version.sorted.all
+    assert_equal [v5, v3, v1, v2, v4], Version.sorted.to_a
   end
 
   def test_completed_should_be_false_when_due_today
diff --git a/test/unit/wiki_test.rb b/test/unit/wiki_test.rb
index e363b41..a852b23 100644
--- a/test/unit/wiki_test.rb
+++ b/test/unit/wiki_test.rb
@@ -78,8 +78,7 @@ class WikiTest < ActiveSupport::TestCase
   end
 
   def test_titleize
-    ja_test = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
-    ja_test.force_encoding('UTF-8') if ja_test.respond_to?(:force_encoding)
+    ja_test = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8')
     assert_equal 'Page_title_with_CAPITALES', Wiki.titleize('page title with CAPITALES')
     assert_equal ja_test, Wiki.titleize(ja_test)
   end
diff --git a/test/unit/workflow_transition_test.rb b/test/unit/workflow_transition_test.rb
new file mode 100644
index 0000000..0b5e1ab
--- /dev/null
+++ b/test/unit/workflow_transition_test.rb
@@ -0,0 +1,93 @@
+# Redmine - project management software
+# Copyright (C) 2006-2014  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
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require File.expand_path('../../test_helper', __FILE__)
+
+class WorkflowTransitionTest < ActiveSupport::TestCase
+  fixtures :roles, :trackers, :issue_statuses
+
+  def setup
+    WorkflowTransition.delete_all
+  end
+
+  def test_replace_transitions_should_create_enabled_transitions
+    w = WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2)
+
+    transitions = {'1' => {
+      '2' => {'always' => '1'},
+      '3' => {'always' => '1'}
+    }}
+    assert_difference 'WorkflowTransition.count' do
+      WorkflowTransition.replace_transitions(Tracker.find(1), Role.find(1), transitions)
+    end
+    assert WorkflowTransition.where(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3).exists?
+  end
+
+  def test_replace_transitions_should_delete_disabled_transitions
+    w1 = WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2)
+    w2 = WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
+
+    transitions = {'1' => {
+      '2' => {'always' => '0'},
+      '3' => {'always' => '1'}
+    }}
+    assert_difference 'WorkflowTransition.count', -1 do
+      WorkflowTransition.replace_transitions(Tracker.find(1), Role.find(1), transitions)
+    end
+    assert !WorkflowTransition.exists?(w1.id)
+  end
+
+  def test_replace_transitions_should_create_enabled_additional_transitions
+    transitions = {'1' => {
+      '2' => {'always' => '0', 'assignee' => '0', 'author' => '1'}
+    }}
+    assert_difference 'WorkflowTransition.count' do
+      WorkflowTransition.replace_transitions(Tracker.find(1), Role.find(1), transitions)
+    end
+    w = WorkflowTransition.where(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2).first
+    assert w
+    assert_equal false, w.assignee
+    assert_equal true, w.author
+  end
+
+  def test_replace_transitions_should_delete_disabled_additional_transitions
+    w = WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :assignee => true)
+
+    transitions = {'1' => {
+      '2' => {'always' => '0', 'assignee' => '0', 'author' => '0'}
+    }}
+    assert_difference 'WorkflowTransition.count', -1 do
+      WorkflowTransition.replace_transitions(Tracker.find(1), Role.find(1), transitions)
+    end
+    assert !WorkflowTransition.exists?(w.id)
+  end
+
+  def test_replace_transitions_should_update_additional_transitions
+    WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :assignee => true)
+
+    transitions = {'1' => {
+      '2' => {'always' => '0', 'assignee' => '0', 'author' => '1'}
+    }}
+    assert_no_difference 'WorkflowTransition.count' do
+      WorkflowTransition.replace_transitions(Tracker.find(1), Role.find(1), transitions)
+    end
+    w = WorkflowTransition.where(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2).first
+    assert w
+    assert_equal false, w.assignee
+    assert_equal true, w.author
+  end
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/redmine.git



More information about the Pkg-ruby-extras-commits mailing list