">
- <%= link_to source.name, :action => 'edit', :id => source%>
- <%= source.auth_method_name %>
- <%= source.host %>
- <%= source.users.count %>
+ <%= link_to(h(source.name), :action => 'edit', :id => source)%>
+ <%= h source.auth_method_name %>
+ <%= h source.host %>
+ <%= h source.users.count %>
<%= link_to l(:button_test), :action => 'test_connection', :id => source %>
<%= link_to l(:button_delete), { :action => 'destroy', :id => source },
diff --git a/app/views/common/_diff.rhtml b/app/views/common/_diff.rhtml
index f7f40fb0..b4327aec 100644
--- a/app/views/common/_diff.rhtml
+++ b/app/views/common/_diff.rhtml
@@ -5,7 +5,7 @@
<% if diff.diff_type == 'sbs' -%>
-<%=to_utf8 table_file.file_name %>
+<%=to_utf8_for_attachments table_file.file_name %>
<% table_file.each_line do |spacing, line| -%>
@@ -17,11 +17,11 @@
<%= line.nb_line_left %>
- <%=to_utf8 line.html_line_left %>
+ <%=to_utf8_for_attachments line.html_line_left %>
<%= line.nb_line_right %>
- <%=to_utf8 line.html_line_right %>
+ <%=to_utf8_for_attachments line.html_line_right %>
<% end -%>
diff --git a/app/views/documents/_form.rhtml b/app/views/documents/_form.rhtml
index b118ebdc..37d67d1e 100644
--- a/app/views/documents/_form.rhtml
+++ b/app/views/documents/_form.rhtml
@@ -1,7 +1,7 @@
<%= error_messages_for 'document' %>
-
<%=l(:field_category)%>
+
<%=l(:field_category)%> *
<%= select('document', 'category_id', DocumentCategory.all.collect {|c| [c.name, c.id]}) %>
<%=l(:field_title)%> *
diff --git a/app/views/journals/index.rxml b/app/views/journals/index.rxml
index fc29ae71..89e25ee4 100644
--- a/app/views/journals/index.rxml
+++ b/app/views/journals/index.rxml
@@ -19,12 +19,13 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
end
xml.content "type" => "html" do
xml.text! '
'
- change.details.each do |detail|
- xml.text! '' + change.render_detail(detail, false) + ' '
+ change.changes.each do |detail|
+ change_content = change.render_detail(detail, false)
+ xml.text!(content_tag(:li, change_content)) if change_content.present?
end
xml.text! ' '
xml.text! textilizable(change, :notes, :only_path => false) unless change.notes.blank?
end
end
end
-end
\ No newline at end of file
+end
diff --git a/app/views/users/show.rhtml b/app/views/users/show.rhtml
index 52060866..ac93ed02 100644
--- a/app/views/users/show.rhtml
+++ b/app/views/users/show.rhtml
@@ -5,6 +5,7 @@
<%= avatar @user, :size => "50" %> <%=h @user.name %>
+<%= call_hook :view_account_left_top, :user => @user %>
<% unless @user.pref.hide_mail %>
<%=l(:field_mail)%>: <%= mail_to(h(escape_javascript(@user.mail)), nil, :encode => 'javascript') %>
@@ -20,6 +21,8 @@
<% end %>
+<%= call_hook :view_account_left_middle, :user => @user %>
+
<% unless @memberships.empty? %>
<%=l(:label_project_plural)%>
diff --git a/app/views/wiki/show.rhtml b/app/views/wiki/show.rhtml
index 92ed3a47..6cc7fbc0 100644
--- a/app/views/wiki/show.rhtml
+++ b/app/views/wiki/show.rhtml
@@ -49,6 +49,7 @@
<%= f.link_to 'Atom', :url => {:controller => 'activities', :action => 'index', :id => @project, :show_wiki_edits => 1, :key => User.current.rss_key} %>
<%= f.link_to 'HTML', :url => {:id => @page.title, :version => @content.version} %>
<%= f.link_to 'TXT', :url => {:id => @page.title, :version => @content.version} %>
+ <%= call_hook(:view_wiki_show_other_formats, {:link_builder => f, :url_params => {:id => @page.title, :version => @content.version}}) %>
<% end if User.current.allowed_to?(:export_wiki_pages, @project) %>
<% content_for :header_tags do %>
diff --git a/config/environment.rb b/config/environment.rb
index 4751b8fb..5f9d178b 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -18,7 +18,7 @@
# ENV['RAILS_ENV'] ||= 'production'
# Specifies gem version of Rails to use when vendor/rails is not present
-RAILS_GEM_VERSION = '2.3.11' unless defined? RAILS_GEM_VERSION
+RAILS_GEM_VERSION = '2.3.12' unless defined? RAILS_GEM_VERSION
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 538265f0..e08c0731 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -931,8 +931,8 @@ en:
text_powered_by: "Powered by %{link}"
text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page."
text_default_encoding: "Default: UTF-8"
- text_mercurial_repo_example: "local repository (e.g. /hgrepo, c:\hgrepo)"
- text_git_repo_example: "a bare and local repository (e.g. /gitrepo, c:\gitrepo)"
+ text_mercurial_repo_example: "local repository (e.g. /hgrepo, c:\\hgrepo)"
+ text_git_repo_example: "a bare and local repository (e.g. /gitrepo, c:\\gitrepo)"
default_role_manager: Manager
default_role_developer: Developer
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index d2b0985e..421b9098 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -968,18 +968,18 @@ pt-BR:
label_my_queries: Minhas consultas personalizadas
text_journal_changed_no_detail: "%{label} atualizado(a)"
label_news_comment_added: Notícia recebeu um comentário
- button_expand_all: Expand all
- button_collapse_all: Collapse all
- label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee
- label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author
- field_effective_date: Due date
+ button_expand_all: Expandir tudo
+ button_collapse_all: Recolher tudo
+ label_additional_workflow_transitions_for_assignee: Transições adicionais permitidas quando o usuário é o responsável pela tarefa
+ label_additional_workflow_transitions_for_author: Transições adicionais permitidas quando o usuário é o autor
+ field_effective_date: Data prevista
label_cvs_path: CVSROOT
- text_powered_by: Powered by %{link}
- text_default_encoding: "Default: UTF-8"
- text_git_repo_example: a bare and local repository (e.g. /gitrepo, c:\gitrepo)
- label_notify_member_plural: Email issue updates
- label_path_encoding: Path encoding
- text_mercurial_repo_example: local repository (e.g. /hgrepo, c:\hgrepo)
+ text_powered_by: Tecnologia empregada por %{link}
+ text_default_encoding: "Padrão: UTF-8"
+ text_git_repo_example: "um repositório local do tipo bare (ex.: /gitrepo, c:\\gitrepo)"
+ label_notify_member_plural: Enviar atualizações da tarefa por e-mail
+ label_path_encoding: Codificação do caminho
+ text_mercurial_repo_example: "repositório local (ex.: /hgrepo, c:\\hgrepo)"
label_cvs_module: Módulo
label_filesystem_path: Diretório raiz
label_darcs_path: Diretório raiz
diff --git a/db/migrate/20100714111651_generalize_journals.rb b/db/migrate/20100714111651_generalize_journals.rb
deleted file mode 100644
index b0ecfcf6..00000000
--- a/db/migrate/20100714111651_generalize_journals.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-#-- copyright
-# ChiliProject is a project management system.
-#
-# Copyright (C) 2010-2011 the ChiliProject Team
-#
-# 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.
-#
-# See doc/COPYRIGHT.rdoc for more details.
-#++
-
-class GeneralizeJournals < ActiveRecord::Migration
- def self.up
- # This is provided here for migrating up after the JournalDetails has been removed
- unless Object.const_defined?("JournalDetails")
- Object.const_set("JournalDetails", Class.new(ActiveRecord::Base))
- end
-
- change_table :journals do |t|
- t.rename :journalized_id, :journaled_id
- t.rename :created_on, :created_at
-
- t.integer :version, :default => 0, :null => false
- t.string :activity_type
- t.text :changes
- t.string :type
-
- t.index :journaled_id
- t.index :activity_type
- t.index :created_at
- t.index :type
- end
-
- Journal.all.group_by(&:journaled_id).each_pair do |id, journals|
- journals.sort_by(&:created_at).each_with_index do |j, idx|
- j.update_attribute(:type, "#{j.journalized_type}Journal")
- j.update_attribute(:version, idx + 1)
- # FIXME: Find some way to choose the right activity here
- j.update_attribute(:activity_type, j.journalized_type.constantize.activity_provider_options.keys.first)
- end
- end
-
- change_table :journals do |t|
- t.remove :journalized_type
- end
-
- JournalDetails.all.each do |detail|
- journal = Journal.find(detail.journal_id)
- changes = journal.changes || {}
- if detail.property == 'attr' # Standard attributes
- changes[detail.prop_key.to_s] = [detail.old_value, detail.value]
- elsif detail.property == 'cf' # Custom fields
- changes["custom_values_" + detail.prop_key.to_s] = [detail.old_value, detail.value]
- elsif detail.property == 'attachment' # Attachment
- changes["attachments_" + detail.prop_key.to_s] = [detail.old_value, detail.value]
- end
- journal.update_attribute(:changes, changes.to_yaml)
- end
-
- # Create creation journals for all activity providers
- providers = Redmine::Activity.providers.collect {|k, v| v.collect(&:constantize) }.flatten.compact.uniq
- providers.each do |p|
- next unless p.table_exists? # Objects not in the DB yet need creation journal entries
- p.find(:all).each do |o|
- unless o.last_journal
- o.send(:update_journal)
- created_at = nil
- [:created_at, :created_on, :updated_at, :updated_on].each do |m|
- if o.respond_to? m
- created_at = o.send(m)
- break
- end
- end
- p "Updating #{o}"
- o.last_journal.update_attribute(:created_at, created_at) if created_at and o.last_journal
- end
- end
- end
-
- # drop_table :journal_details
- end
-
- def self.down
- # create_table "journal_details", :force => true do |t|
- # t.integer "journal_id", :default => 0, :null => false
- # t.string "property", :limit => 30, :default => "", :null => false
- # t.string "prop_key", :limit => 30, :default => "", :null => false
- # t.string "old_value"
- # t.string "value"
- # end
-
- change_table "journals" do |t|
- t.rename :journaled_id, :journalized_id
- t.rename :created_at, :created_on
-
- t.string :journalized_type, :limit => 30, :default => "", :null => false
- end
-
- custom_field_names = CustomField.all.group_by(&:type)[IssueCustomField].collect(&:name)
- Journal.all.each do |j|
- # Can't used j.journalized.class.name because the model changes make it nil
- j.update_attribute(:journalized_type, j.type.to_s.sub("Journal","")) if j.type.present?
- end
-
- change_table "journals" do |t|
- t.remove_index :journaled_id
- t.remove_index :activity_type
- t.remove_index :created_at
- t.remove_index :type
-
- t.remove :type
- t.remove :version
- t.remove :activity_type
- t.remove :changes
- end
-
- # add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id"
- # add_index "journals", ["journalized_id", "journalized_type"], :name => "journals_journalized_id"
- end
-end
diff --git a/db/migrate/20100714111651_prepare_journals_for_acts_as_journalized.rb b/db/migrate/20100714111651_prepare_journals_for_acts_as_journalized.rb
new file mode 100644
index 00000000..66f47098
--- /dev/null
+++ b/db/migrate/20100714111651_prepare_journals_for_acts_as_journalized.rb
@@ -0,0 +1,55 @@
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2011 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class PrepareJournalsForActsAsJournalized < ActiveRecord::Migration
+ def self.up
+ # This is provided here for migrating up after the JournalDetails has been removed
+ unless Object.const_defined?("JournalDetails")
+ Object.const_set("JournalDetails", Class.new(ActiveRecord::Base))
+ end
+
+ change_table :journals do |t|
+ t.rename :journalized_id, :journaled_id
+ t.rename :created_on, :created_at
+
+ t.integer :version, :default => 0, :null => false
+ t.string :activity_type
+ t.text :changes
+ t.string :type
+
+ t.index :journaled_id
+ t.index :activity_type
+ t.index :created_at
+ t.index :type
+ end
+
+ end
+
+ def self.down
+ change_table "journals" do |t|
+ t.rename :journaled_id, :journalized_id
+ t.rename :created_at, :created_on
+
+ t.remove_index :journaled_id
+ t.remove_index :activity_type
+ t.remove_index :created_at
+ t.remove_index :type
+
+ t.remove :type
+ t.remove :version
+ t.remove :activity_type
+ t.remove :changes
+ end
+
+ end
+end
diff --git a/db/migrate/20100714111652_update_journals_for_acts_as_journalized.rb b/db/migrate/20100714111652_update_journals_for_acts_as_journalized.rb
new file mode 100644
index 00000000..6792951f
--- /dev/null
+++ b/db/migrate/20100714111652_update_journals_for_acts_as_journalized.rb
@@ -0,0 +1,47 @@
+Redmine::Activity.providers.values.flatten.uniq.collect(&:underscore).each {|klass| require_dependency klass }
+
+class UpdateJournalsForActsAsJournalized < ActiveRecord::Migration
+ def self.up
+ # This is provided here for migrating up after the JournalDetails has been removed
+ unless Object.const_defined?("JournalDetails")
+ Object.const_set("JournalDetails", Class.new(ActiveRecord::Base))
+ end
+
+ say_with_time("Updating existing Journals...") do
+ Journal.all.group_by(&:journaled_id).each_pair do |id, journals|
+ journals.sort_by(&:created_at).each_with_index do |j, idx|
+ # Recast the basic Journal into it's STI journalized class so callbacks work (#467)
+ klass_name = "#{j.journalized_type}Journal"
+ j = j.becomes(klass_name.constantize)
+ j.type = klass_name
+ j.version = idx + 2 # initial journal should be 1
+ j.activity_type = j.journalized_type.constantize.activity_provider_options.keys.first
+ begin
+ j.save(false)
+ rescue ActiveRecord::RecordInvalid => ex
+ puts "Error saving: #{j.class.to_s}##{j.id} - #{ex.message}"
+ end
+
+ end
+ end
+ end
+
+ change_table :journals do |t|
+ t.remove :journalized_type
+ end
+ end
+
+ def self.down
+ change_table "journals" do |t|
+ t.string :journalized_type, :limit => 30, :default => "", :null => false
+ end
+
+ custom_field_names = CustomField.all.group_by(&:type)[IssueCustomField].collect(&:name)
+ Journal.all.each do |j|
+ # Can't used j.journalized.class.name because the model changes make it nil
+ j.update_attribute(:journalized_type, j.type.to_s.sub("Journal","")) if j.type.present?
+ end
+
+ end
+end
+
diff --git a/db/migrate/20100714111653_build_initial_journals_for_acts_as_journalized.rb b/db/migrate/20100714111653_build_initial_journals_for_acts_as_journalized.rb
new file mode 100644
index 00000000..3574e642
--- /dev/null
+++ b/db/migrate/20100714111653_build_initial_journals_for_acts_as_journalized.rb
@@ -0,0 +1,80 @@
+class BuildInitialJournalsForActsAsJournalized < ActiveRecord::Migration
+ def self.up
+ # This is provided here for migrating up after the JournalDetails has been removed
+ unless Object.const_defined?("JournalDetails")
+ Object.const_set("JournalDetails", Class.new(ActiveRecord::Base))
+ end
+
+ # Reset class and subclasses, otherwise they will try to save using older attributes
+ Journal.reset_column_information
+ Journal.send(:subclasses).each do |klass|
+ klass.reset_column_information if klass.respond_to?(:reset_column_information)
+ end
+
+ providers = Redmine::Activity.providers.collect {|k, v| v.collect(&:constantize) }.flatten.compact.uniq
+ providers.each do |p|
+ next unless p.table_exists? # Objects not in the DB yet need creation journal entries
+
+ say_with_time("Building initial journals for #{p.class_name}") do
+
+ activity_type = p.activity_provider_options.keys.first
+
+ p.find(:all).each do |o|
+ # Create initial journals
+ new_journal = o.journals.build
+ # Mock up a list of changes for the creation journal based on Class defaults
+ new_attributes = o.class.new.attributes.except(o.class.primary_key,
+ o.class.inheritance_column,
+ :updated_on,
+ :updated_at,
+ :lock_version,
+ :lft,
+ :rgt)
+ creation_changes = {}
+ new_attributes.each do |name, default_value|
+ # Set changes based on the initial value to current. Can't get creation value without
+ # rebuiling the object history
+ creation_changes[name] = [default_value, o.send(name)] # [initial_value, creation_value]
+ end
+ new_journal.changes = creation_changes
+ new_journal.version = 1
+ new_journal.activity_type = activity_type
+
+ if o.respond_to?(:author)
+ new_journal.user = o.author
+ elsif o.respond_to?(:user)
+ new_journal.user = o.user
+ end
+ # Using rescue and save! here because either the Journal or the
+ # touched record could fail. This will catch either error and continue
+ begin
+ new_journal.save!
+
+ new_journal.reload
+
+ # Backdate journal
+ if o.respond_to?(:created_at)
+ new_journal.update_attribute(:created_at, o.created_at)
+ elsif o.respond_to?(:created_on)
+ new_journal.update_attribute(:created_at, o.created_on)
+ end
+ rescue ActiveRecord::RecordInvalid => ex
+ if new_journal.errors.count == 1 && new_journal.errors.first[0] == "version"
+ # Skip, only error was from creating the initial journal for a record that already had one.
+ else
+ puts "ERROR: errors creating the initial journal for #{o.class.to_s}##{o.id.to_s}:"
+ puts " #{ex.message}"
+ end
+ end
+ end
+
+ end
+ end
+
+ end
+
+ def self.down
+ # No-op
+ end
+
+end
diff --git a/db/migrate/20100714111654_add_changes_from_journal_details_for_acts_as_journalized.rb b/db/migrate/20100714111654_add_changes_from_journal_details_for_acts_as_journalized.rb
new file mode 100644
index 00000000..43ef3256
--- /dev/null
+++ b/db/migrate/20100714111654_add_changes_from_journal_details_for_acts_as_journalized.rb
@@ -0,0 +1,35 @@
+class AddChangesFromJournalDetailsForActsAsJournalized < ActiveRecord::Migration
+ def self.up
+ # This is provided here for migrating up after the JournalDetails has been removed
+ unless Object.const_defined?("JournalDetails")
+ Object.const_set("JournalDetails", Class.new(ActiveRecord::Base))
+ end
+
+ say_with_time("Adding changes from JournalDetails") do
+ JournalDetails.all.each do |detail|
+ journal = Journal.find(detail.journal_id)
+ changes = journal.changes || {}
+ if detail.property == 'attr' # Standard attributes
+ changes[detail.prop_key.to_s] = [detail.old_value, detail.value]
+ elsif detail.property == 'cf' # Custom fields
+ changes["custom_values_" + detail.prop_key.to_s] = [detail.old_value, detail.value]
+ elsif detail.property == 'attachment' # Attachment
+ changes["attachments_" + detail.prop_key.to_s] = [detail.old_value, detail.value]
+ end
+ begin
+ journal.update_attribute(:changes, changes.to_yaml)
+ rescue ActiveRecord::RecordInvalid => ex
+ puts "Error saving: #{journal.class.to_s}##{journal.id} - #{ex.message}"
+ end
+
+ end
+
+ end
+
+ end
+
+ def self.down
+ # No-op
+ end
+
+end
diff --git a/db/migrate/20100804112053_merge_wiki_versions_with_journals.rb b/db/migrate/20100804112053_merge_wiki_versions_with_journals.rb
index 8d13d13e..3e7d6517 100644
--- a/db/migrate/20100804112053_merge_wiki_versions_with_journals.rb
+++ b/db/migrate/20100804112053_merge_wiki_versions_with_journals.rb
@@ -20,7 +20,7 @@ class MergeWikiVersionsWithJournals < ActiveRecord::Migration
WikiContent::Version.find_by_sql("SELECT * FROM wiki_content_versions").each do |wv|
journal = WikiContentJournal.create!(:journaled_id => wv.wiki_content_id, :user_id => wv.author_id,
- :notes => wv.comments, :activity_type => "wiki_edits")
+ :notes => wv.comments, :created_at => wv.updated_on, :activity_type => "wiki_edits")
changes = {}
changes["compression"] = wv.compression
changes["data"] = wv.data
diff --git a/doc/CHANGELOG.rdoc b/doc/CHANGELOG.rdoc
index 42add1c4..f0b27a59 100644
--- a/doc/CHANGELOG.rdoc
+++ b/doc/CHANGELOG.rdoc
@@ -7,9 +7,11 @@
* Bug #343: Review Gantt and Calender links from 07cf681
* Bug #345: Entering large numbers for 'Estimated Time' fails with 'Invalid big Decimal Value'
* Bug #346: I18n YAML files not parsable with psych yaml library
-* Bug #383: Fix broken tests in unstable
+* Bug #383: Fix broken tests in unstable caused by conflicting to_utf8 method names
* Bug #389: Context menu doesn't work in Opera
* Bug #390: mysql2 incompatibility in WikiPage model
+* Bug #397: FIXME in generalize_journals migration
+* Bug #398: Remove helper calls from IssuesController
* Bug #400: Review and fix the Activity event types
* Bug #401: Move JournalsHelpers from aaj to the core
* Bug #403: [AAJ] Attachment has it's files and documents activity provider removed but only documents added
@@ -27,17 +29,42 @@
* Bug #419: Issue list context menu not working in IE9
* Bug #422: cvs test are not working
* Bug #423: Remove explicit render from WikiController#show
+* Bug #437: Encoding error on Ruby 1.9 in pdf exports
+* Bug #441: Creating a Journal does not update the journaled record's updated_at/on attribute
+* Bug #442: Issue atom feed shows "issue creation" journal, didn't before
+* Bug #443: IssuesControllerTest.test_show_atom test failure on 1.9.2
+* Bug #444: ChangesetTest and RepositoryGitTest test failures on 1.9.2
+* Bug #445: Track initial attributes in a Journal when created
+* Bug #453: Update to Rails 2.3.12 to fix some bugs
+* Bug #466: SVN: Apache initialization error
+* Bug #467: uninitialized constant Journal::Journaled
+* Bug #468: Lost WIKI history timestamps during 2.0.0rc1 upgrade.
+* Bug #469: Wong URL for WIKI activity entries in 2.0.0rc2
+* Bug #474: Changesets are displaying the wrong user and commit date in the Activity
+* Bug #475: News, docs, changesets and time activities were not migrated to 2.0.0rc2
+* Bug #477: Getting rid of "rake/rdoctask is deprecated." warning
+* Bug #479: Generalize Journals migrations does too much
+* Bug #480: Issue Journal replies get ignored
+* Bug #493: uninitialized constant TimeEntryJournal
+* Bug #501: Updating a ticket that was created by email forces a "change" of description
+* Bug #503: 2.0.0RC3 - YAML Parser fails in ruby 1.9
* Feature #112: Provide a library function to detect the database type used
+* Feature #123: Review and Merge acts_as_journalized
* Feature #196: Upgrade to Rails 2.3-latest
+* Feature #197: Rake task to manage copyright inside of source files
* Feature #216: Remove the rubygems hack from boot.rb
* Feature #217: Remove the hack to require a specific i18n version in boot.rb
* Feature #269: Refactor lib/redmine/menu_manager.rb to increase extensibility
* Feature #279: Optional start date on Versions
+* Feature #288: Review latest Redmine commits
* Feature #289: Switch to helper :all
* Feature #290: Add bundler
* Feature #310: Option to skip mail notifications on issue updates
* Feature #350: Setting model should use Rails.cache instead of class variable
* Feature #416: Refactor watcher_tag and watcher_link to use css selectors for the replace action
+* Feature #436: Clean up trailing whitespace and tabs
+* Feature #462: pt-BR translation update
+* Feature #473: pt-BR translation fix
* Task #123: Review and Merge acts_as_journalized
* Task #197: Rake task to manage copyright inside of source files
* Task #288: Review latest Redmine commits
@@ -59,6 +86,11 @@
** Patch #7598: Extensible MailHandler
** Patch #7795: Internal server error at journals#index with custom fields
+== 2011-06-27 v1.5.0
+
+* Bug #490: XSS in app/views/auth_sources/index.html.erb
+* Feature #488: Hook for additional formats on Wiki#show page
+
== 2011-05-27 v1.4.0
* Bug #81: Replace favicon
diff --git a/extra/svn/Redmine.pm b/extra/svn/Redmine.pm
index 8e14822c..a780f114 100644
--- a/extra/svn/Redmine.pm
+++ b/extra/svn/Redmine.pm
@@ -480,6 +480,7 @@ sub is_member {
sub get_project_identifier {
my $r = shift;
+ my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
my $location = $r->location;
my ($identifier) = $r->uri =~ m{$location/*([^/]+)};
$identifier =~ s/\.git$// if (defined $cfg->{RedmineGitSmartHttp} and $cfg->{RedmineGitSmartHttp});
diff --git a/lib/redmine/version.rb b/lib/redmine/version.rb
index 1b4c4673..abd878ef 100644
--- a/lib/redmine/version.rb
+++ b/lib/redmine/version.rb
@@ -32,7 +32,7 @@ module Redmine
#
# 2.0.0debian-2
def self.special
- 'RC1'
+ ''
end
def self.revision
diff --git a/lib/tasks/documentation.rake b/lib/tasks/documentation.rake
index 8da8f434..6a4d4848 100644
--- a/lib/tasks/documentation.rake
+++ b/lib/tasks/documentation.rake
@@ -18,7 +18,7 @@ Rake::Task["doc/app/index.html"].clear
namespace :doc do
desc "Generate documentation for the application. Set custom template with TEMPLATE=/path/to/rdoc/template.rb or title with TITLE=\"Custom Title\""
- Rake::RDocTask.new("app") { |rdoc|
+ RDoc::Task.new("app") { |rdoc|
rdoc.rdoc_dir = 'doc/app'
rdoc.template = ENV['template'] if ENV['template']
rdoc.title = ENV['title'] || "ChiliProject"
diff --git a/lib/tasks/release.rake b/lib/tasks/release.rake
new file mode 100644
index 00000000..2f793e80
--- /dev/null
+++ b/lib/tasks/release.rake
@@ -0,0 +1,37 @@
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2011 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+require 'fileutils'
+
+desc "Package up a ChiliProject release from git. example: `rake release[1.1.0]`"
+task :release, [:version] do |task, args|
+ version = args[:version]
+ abort "Missing version in the form of 1.0.0" unless version.present?
+
+ dir = Pathname.new(ENV['HOME']) + 'dev' + 'chiliproject' + 'packages'
+ FileUtils.mkdir_p dir
+
+ commands = [
+ "cd #{dir}",
+ "git clone git://github.com/chiliproject/chiliproject.git chiliproject-#{version}",
+ "cd chiliproject-#{version}/",
+ "git checkout v#{version}",
+ "rm -vRf #{dir}/chiliproject-#{version}/.git",
+ "cd #{dir}",
+ "tar -zcvf chiliproject-#{version}.tar.gz chiliproject-#{version}",
+ "zip -r -9 chiliproject-#{version}.zip chiliproject-#{version}",
+ "md5sum chiliproject-#{version}.tar.gz chiliproject-#{version}.zip > chiliproject-#{version}.md5sum",
+ "echo 'Release ready'"
+ ].join(' && ')
+ system(commands)
+end
diff --git a/public/javascripts/controls.js b/public/javascripts/controls.js
index ca29aefd..5137ab51 100644
--- a/public/javascripts/controls.js
+++ b/public/javascripts/controls.js
@@ -1,6 +1,8 @@
-// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
-// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
+// script.aculo.us controls.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
+
+// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2010 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2010 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
diff --git a/public/javascripts/dragdrop.js b/public/javascripts/dragdrop.js
index 07229f98..9ebfe24d 100644
--- a/public/javascripts/dragdrop.js
+++ b/public/javascripts/dragdrop.js
@@ -1,5 +1,6 @@
-// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+// script.aculo.us dragdrop.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
+
+// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -311,7 +312,7 @@ var Draggable = Class.create({
tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
- var pos = Position.cumulativeOffset(this.element);
+ var pos = this.element.cumulativeOffset();
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this);
@@ -373,7 +374,7 @@ var Draggable = Class.create({
if (this.options.scroll == window) {
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
} else {
- p = Position.page(this.options.scroll);
+ p = Position.page(this.options.scroll).toArray();
p[0] += this.options.scroll.scrollLeft + Position.deltaX;
p[1] += this.options.scroll.scrollTop + Position.deltaY;
p.push(p[0]+this.options.scroll.offsetWidth);
@@ -454,7 +455,7 @@ var Draggable = Class.create({
},
draw: function(point) {
- var pos = Position.cumulativeOffset(this.element);
+ var pos = this.element.cumulativeOffset();
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
@@ -730,7 +731,7 @@ var Sortable = {
}
// keep reference
- this.sortables[element.id] = options;
+ this.sortables[element.identify()] = options;
// for onupdate
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
@@ -825,7 +826,7 @@ var Sortable = {
hide().addClassName('dropmarker').setStyle({position:'absolute'});
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
- var offsets = Position.cumulativeOffset(dropon);
+ var offsets = dropon.cumulativeOffset();
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
if(position=='after')
diff --git a/public/javascripts/effects.js b/public/javascripts/effects.js
index 5a639d2d..860ddc09 100644
--- a/public/javascripts/effects.js
+++ b/public/javascripts/effects.js
@@ -1,4 +1,6 @@
-// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// script.aculo.us effects.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
+
+// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
@@ -145,14 +147,13 @@ var Effect = {
'blind': ['BlindDown','BlindUp'],
'appear': ['Appear','Fade']
},
- toggle: function(element, effect) {
+ toggle: function(element, effect, options) {
element = $(element);
- effect = (effect || 'appear').toLowerCase();
- var options = Object.extend({
+ effect = (effect || 'appear').toLowerCase();
+
+ return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
- }, arguments[2] || { });
- Effect[element.visible() ?
- Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }, options || {}));
}
};
@@ -228,12 +229,6 @@ Effect.Queue = Effect.Queues.get('global');
Effect.Base = Class.create({
position: null,
start: function(options) {
- function codeForEvent(options,eventName){
- return (
- (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
- (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
- );
- }
if (options && options.transition === false) options.transition = Effect.Transitions.linear;
this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
this.currentFrame = 0;
diff --git a/public/javascripts/prototype.js b/public/javascripts/prototype.js
index dfe8ab4e..ba12e075 100644
--- a/public/javascripts/prototype.js
+++ b/public/javascripts/prototype.js
@@ -1,5 +1,5 @@
-/* Prototype JavaScript framework, version 1.6.0.3
- * (c) 2005-2008 Sam Stephenson
+/* Prototype JavaScript framework, version 1.7
+ * (c) 2005-2010 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
@@ -7,42 +7,71 @@
*--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.6.0.3',
- Browser: {
- IE: !!(window.attachEvent &&
- navigator.userAgent.indexOf('Opera') === -1),
- Opera: navigator.userAgent.indexOf('Opera') > -1,
- WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
- Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
- navigator.userAgent.indexOf('KHTML') === -1,
- MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
- },
+ Version: '1.7',
+
+ Browser: (function(){
+ var ua = navigator.userAgent;
+ var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
+ return {
+ IE: !!window.attachEvent && !isOpera,
+ Opera: isOpera,
+ WebKit: ua.indexOf('AppleWebKit/') > -1,
+ Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
+ MobileSafari: /Apple.*Mobile/.test(ua)
+ }
+ })(),
BrowserFeatures: {
XPath: !!document.evaluate,
+
SelectorsAPI: !!document.querySelector,
- ElementExtensions: !!window.HTMLElement,
- SpecificElementExtensions:
- document.createElement('div')['__proto__'] &&
- document.createElement('div')['__proto__'] !==
- document.createElement('form')['__proto__']
+
+ ElementExtensions: (function() {
+ var constructor = window.Element || window.HTMLElement;
+ return !!(constructor && constructor.prototype);
+ })(),
+ SpecificElementExtensions: (function() {
+ if (typeof window.HTMLDivElement !== 'undefined')
+ return true;
+
+ var div = document.createElement('div'),
+ form = document.createElement('form'),
+ isSupported = false;
+
+ if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
+ isSupported = true;
+ }
+
+ div = form = null;
+
+ return isSupported;
+ })()
},
ScriptFragment: '