From 8d5617fc8b68d96f7d2caa318bb29e27b089c733 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 14 Feb 2011 08:45:34 +0000 Subject: [PATCH 001/440] scm: add scm command and version methods at repository models (#4273). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4822 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository.rb | 24 ++++++++++++++++++++++-- app/models/repository/bazaar.rb | 6 +++--- app/models/repository/cvs.rb | 6 +++--- app/models/repository/darcs.rb | 6 +++--- app/models/repository/filesystem.rb | 6 +++--- app/models/repository/git.rb | 4 ++-- app/models/repository/mercurial.rb | 2 +- app/models/repository/subversion.rb | 4 ++-- 8 files changed, 39 insertions(+), 19 deletions(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index 3d463b82..1fbcf5f5 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -37,6 +37,10 @@ class Repository < ActiveRecord::Base write_attribute(:root_url, arg ? arg.to_s.strip : nil) end + def scm_adapter + self.class.scm_adapter_class + end + def scm @scm ||= self.scm_adapter.new url, root_url, login, password update_attribute(:root_url, @scm.root_url) if root_url.blank? @@ -46,7 +50,7 @@ class Repository < ActiveRecord::Base def scm_name self.class.scm_name end - + def supports_cat? scm.supports_cat? end @@ -204,7 +208,23 @@ class Repository < ActiveRecord::Base rescue nil end - + + def self.scm_adapter_class + nil + end + + def self.scm_command + self.scm_adapter_class.nil? ? "" : self.scm_adapter_class.client_command + end + + def self.scm_version_string + self.scm_adapter_class.nil? ? "" : self.scm_adapter_class.client_version_string + end + + def self.scm_available + self.scm_adapter_class.nil? ? false : self.scm_adapter_class.client_available + end + private def before_save diff --git a/app/models/repository/bazaar.rb b/app/models/repository/bazaar.rb index ec953bd4..9d7977e7 100644 --- a/app/models/repository/bazaar.rb +++ b/app/models/repository/bazaar.rb @@ -21,14 +21,14 @@ class Repository::Bazaar < Repository attr_protected :root_url validates_presence_of :url - def scm_adapter + def self.scm_adapter_class Redmine::Scm::Adapters::BazaarAdapter end - + def self.scm_name 'Bazaar' end - + def entries(path=nil, identifier=nil) entries = scm.entries(path, identifier) if entries diff --git a/app/models/repository/cvs.rb b/app/models/repository/cvs.rb index dbbb4694..c0cac5cd 100644 --- a/app/models/repository/cvs.rb +++ b/app/models/repository/cvs.rb @@ -21,14 +21,14 @@ require 'digest/sha1' class Repository::Cvs < Repository validates_presence_of :url, :root_url - def scm_adapter + def self.scm_adapter_class Redmine::Scm::Adapters::CvsAdapter end - + def self.scm_name 'CVS' end - + def entry(path=nil, identifier=nil) rev = identifier.nil? ? nil : changesets.find_by_revision(identifier) scm.entry(path, rev.nil? ? nil : rev.committed_on) diff --git a/app/models/repository/darcs.rb b/app/models/repository/darcs.rb index 43fb0294..dc3f0cee 100644 --- a/app/models/repository/darcs.rb +++ b/app/models/repository/darcs.rb @@ -20,14 +20,14 @@ require 'redmine/scm/adapters/darcs_adapter' class Repository::Darcs < Repository validates_presence_of :url - def scm_adapter + def self.scm_adapter_class Redmine::Scm::Adapters::DarcsAdapter end - + def self.scm_name 'Darcs' end - + def entry(path=nil, identifier=nil) patch = identifier.nil? ? nil : changesets.find_by_revision(identifier) scm.entry(path, patch.nil? ? nil : patch.scmid) diff --git a/app/models/repository/filesystem.rb b/app/models/repository/filesystem.rb index da096cc0..4be6b528 100644 --- a/app/models/repository/filesystem.rb +++ b/app/models/repository/filesystem.rb @@ -24,14 +24,14 @@ class Repository::Filesystem < Repository attr_protected :root_url validates_presence_of :url - def scm_adapter + def self.scm_adapter_class Redmine::Scm::Adapters::FilesystemAdapter end - + def self.scm_name 'Filesystem' end - + def entries(path=nil, identifier=nil) scm.entries(path, identifier) end diff --git a/app/models/repository/git.rb b/app/models/repository/git.rb index 9349f3c1..26cb84db 100644 --- a/app/models/repository/git.rb +++ b/app/models/repository/git.rb @@ -21,10 +21,10 @@ class Repository::Git < Repository attr_protected :root_url validates_presence_of :url - def scm_adapter + def self.scm_adapter_class Redmine::Scm::Adapters::GitAdapter end - + def self.scm_name 'Git' end diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index 102c6dda..557b9a4d 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -24,7 +24,7 @@ class Repository::Mercurial < Repository attr_protected :root_url validates_presence_of :url - def scm_adapter + def self.scm_adapter_class Redmine::Scm::Adapters::MercurialAdapter end diff --git a/app/models/repository/subversion.rb b/app/models/repository/subversion.rb index 091d1413..05936929 100644 --- a/app/models/repository/subversion.rb +++ b/app/models/repository/subversion.rb @@ -22,10 +22,10 @@ class Repository::Subversion < Repository validates_presence_of :url validates_format_of :url, :with => /^(http|https|svn(\+[^\s:\/\\]+)?|file):\/\/.+/i - def scm_adapter + def self.scm_adapter_class Redmine::Scm::Adapters::SubversionAdapter end - + def self.scm_name 'Subversion' end From e2f79f7c0d7e7eaa0295d1be4e8306fe3b6dad68 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 14 Feb 2011 08:45:54 +0000 Subject: [PATCH 002/440] scm: git: remove localtime (#6346). No needs to use localtime. If we use localtime, we should clone. See r4794 and r4802. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4823 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/git_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index a241f839..88514439 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -109,7 +109,7 @@ module Redmine begin id = lines[0].split[1] author = lines[1].match('Author:\s+(.*)$')[1] - time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1]).localtime + time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1]) Revision.new({ :identifier => id, From 9b68c6701fda58842b8f965cb421f0a5cd3f9f84 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 02:12:19 +0000 Subject: [PATCH 003/440] scm: catch CommandFailed during bulk Repository.fetch_changesets (#4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4824 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index 1fbcf5f5..4ddc7343 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -184,7 +184,11 @@ class Repository < ActiveRecord::Base def self.fetch_changesets Project.active.has_module(:repository).find(:all, :include => :repository).each do |project| if project.repository - project.repository.fetch_changesets + begin + project.repository.fetch_changesets + rescue Redmine::Scm::Adapters::CommandFailed => e + logger.error "Repository: error during fetching changesets: #{e.message}" + end end end end From 323c36b3c3dd88b3da2642b63df1ba1743c78c67 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 02:12:39 +0000 Subject: [PATCH 004/440] scm: subversion: refactor getting svn version and add lib test (#4273). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4825 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/subversion_adapter.rb | 22 ++++++++++--------- .../scm/adapters/subversion_adapter_test.rb | 20 +++++++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb index c17d7a5e..802dc4a1 100644 --- a/lib/redmine/scm/adapters/subversion_adapter.rb +++ b/lib/redmine/scm/adapters/subversion_adapter.rb @@ -38,19 +38,21 @@ module Redmine def client_version @@client_version ||= (svn_binary_version || []) end + + def client_available + !client_version.empty? + end def svn_binary_version - cmd = "#{sq_bin} --version" - version = nil - shellout(cmd) do |io| - # Read svn version in first returned line - if m = io.read.to_s.match(%r{\A(.*?)((\d+\.)+\d+)}) - version = m[2].scan(%r{\d+}).collect(&:to_i) - end - end - return nil if $? && $?.exitstatus != 0 - version + scm_version = scm_version_from_command_line + if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) + m[2].scan(%r{\d+}).collect(&:to_i) + end end + + def scm_version_from_command_line + shellout("#{sq_bin} --version") { |io| io.read }.to_s + end end # Get info about the svn repository 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 966a8292..1d8b9cbe 100644 --- a/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb @@ -24,12 +24,32 @@ begin if repository_configured?('subversion') def setup + repo_path = "file://#{self.class.repository_path('subversion')}" + @adapter = Redmine::Scm::Adapters::SubversionAdapter.new(repo_path) 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 + end + + 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 From 2e85bd621bf11bde3651107280697a72c18ccdd0 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 02:29:47 +0000 Subject: [PATCH 005/440] scm: subversion: change unit app test project id from 1 to 3. Fixtures have project id 1 subversion changesets and changes. Change file:/// to file://. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4826 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_subversion_test.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/unit/repository_subversion_test.rb b/test/unit/repository_subversion_test.rb index fd761823..5e0b0718 100644 --- a/test/unit/repository_subversion_test.rb +++ b/test/unit/repository_subversion_test.rb @@ -21,8 +21,9 @@ class RepositorySubversionTest < ActiveSupport::TestCase fixtures :projects, :repositories, :enabled_modules, :users, :roles def setup - @project = Project.find(1) - assert @repository = Repository::Subversion.create(:project => @project, :url => "file:///#{self.class.repository_path('subversion')}") + @project = Project.find(3) + assert @repository = Repository::Subversion.create(:project => @project, + :url => "file://#{self.class.repository_path('subversion')}") end if repository_configured?('subversion') @@ -74,7 +75,7 @@ class RepositorySubversionTest < ActiveSupport::TestCase end def test_directory_listing_with_square_brackets_in_base - @project = Project.find(1) + @project = Project.find(3) @repository = Repository::Subversion.create(:project => @project, :url => "file:///#{self.class.repository_path('subversion')}/subversion_test/[folder_with_brackets]") @repository.fetch_changesets From 8b3a8d73beffed995b3095c3c070bbc99f330b8e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 05:33:25 +0000 Subject: [PATCH 006/440] scm: subversion: change newlines LF to CRLF at lib/redmine/scm/adapters/subversion_adapter.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4827 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/subversion_adapter.rb | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb index 802dc4a1..37d5bcf4 100644 --- a/lib/redmine/scm/adapters/subversion_adapter.rb +++ b/lib/redmine/scm/adapters/subversion_adapter.rb @@ -38,21 +38,21 @@ module Redmine def client_version @@client_version ||= (svn_binary_version || []) end - - def client_available - !client_version.empty? - end + + def client_available + !client_version.empty? + end def svn_binary_version - scm_version = scm_version_from_command_line - if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) - m[2].scan(%r{\d+}).collect(&:to_i) - end + scm_version = scm_version_from_command_line + if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) + m[2].scan(%r{\d+}).collect(&:to_i) + end + end + + def scm_version_from_command_line + shellout("#{sq_bin} --version") { |io| io.read }.to_s end - - def scm_version_from_command_line - shellout("#{sq_bin} --version") { |io| io.read }.to_s - end end # Get info about the svn repository @@ -185,6 +185,7 @@ module Redmine def diff(path, identifier_from, identifier_to=nil, type="inline") path ||= '' identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : '' + identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : (identifier_from.to_i - 1) cmd = "#{self.class.sq_bin} diff -r " From 62ea9bd91593e9c71e9b113e497d9e89e05fadbd Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 05:58:11 +0000 Subject: [PATCH 007/440] scm: mercurial: switch shell quote revision with argument. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4828 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index f8f925d4..58e9a269 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -93,7 +93,7 @@ module Redmine path ||= '' entries = Entries.new cmd = "#{self.class.sq_bin} -R #{target('')} --cwd #{target('')} locate" - cmd << " -r #{hgrev(identifier)}" + cmd << " -r #{hgrev(identifier, true)}" cmd << " " + shell_quote("path:#{path}") unless path.empty? shellout(cmd) do |io| io.each_line do |line| @@ -120,9 +120,9 @@ module Redmine revisions = Revisions.new cmd = "#{self.class.sq_bin} --debug --encoding utf8 -R #{target('')} log -C --style #{shell_quote self.class.template_path}" if identifier_from && identifier_to - cmd << " -r #{hgrev(identifier_from)}:#{hgrev(identifier_to)}" + cmd << " -r #{hgrev(identifier_from, true)}:#{hgrev(identifier_to, true)}" elsif identifier_from - cmd << " -r #{hgrev(identifier_from)}:" + cmd << " -r #{hgrev(identifier_from, true)}:" end cmd << " --limit #{options[:limit].to_i}" if options[:limit] cmd << " #{shell_quote path}" unless path.blank? @@ -168,10 +168,10 @@ module Redmine diff_args = '' diff = [] if identifier_to - diff_args = "-r #{hgrev(identifier_to)} -r #{hgrev(identifier_from)}" + diff_args = "-r #{hgrev(identifier_to, true)} -r #{hgrev(identifier_from, true)}" else if self.class.client_version_above?([1, 2]) - diff_args = "-c #{hgrev(identifier_from)}" + diff_args = "-c #{hgrev(identifier_from, true)}" else return [] end @@ -189,7 +189,7 @@ module Redmine def cat(path, identifier=nil) cmd = "#{self.class.sq_bin} -R #{target('')} cat" - cmd << " -r #{hgrev(identifier)}" + cmd << " -r #{hgrev(identifier, true)}" cmd << " #{target(path)}" cat = nil shellout(cmd) do |io| @@ -204,7 +204,7 @@ module Redmine path ||= '' cmd = "#{self.class.sq_bin} -R #{target('')}" cmd << " annotate -ncu" - cmd << " -r #{hgrev(identifier)}" + cmd << " -r #{hgrev(identifier, true)}" cmd << " #{target(path)}" blame = Annotate.new shellout(cmd) do |io| @@ -227,8 +227,10 @@ module Redmine end # Returns correct revision identifier - def hgrev(identifier) - shell_quote(identifier.blank? ? 'tip' : identifier.to_s) + def hgrev(identifier, sq=false) + rev = identifier.blank? ? 'tip' : identifier.to_s + rev = shell_quote(rev) if sq + rev end private :hgrev end From f62cccfdc6d4119842cdfed05371121e19277a7c Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 05:58:31 +0000 Subject: [PATCH 008/440] scm: git: add methods of getting git version and add unit lib test (#4273). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4829 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/git_adapter.rb | 15 +++++++++++++++ .../redmine/scm/adapters/git_adapter_test.rb | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index 88514439..ce46057c 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -33,9 +33,24 @@ module Redmine @@sq_bin ||= shell_quote(GIT_BIN) end + def client_version + @@client_version ||= (scm_command_version || []) + end + def client_available !client_version.empty? end + + def scm_command_version + scm_version = scm_version_from_command_line + if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) + m[2].scan(%r{\d+}).collect(&:to_i) + end + end + + def scm_version_from_command_line + shellout("#{sq_bin} --version") { |io| io.read }.to_s + end end def info 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 049296d9..52aecd92 100644 --- a/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb @@ -15,6 +15,15 @@ begin @adapter = Redmine::Scm::Adapters::GitAdapter.new(REPOSITORY_PATH) 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 + def test_branches assert_equal @adapter.branches, ['master', 'test_branch'] end @@ -78,6 +87,14 @@ begin last_rev.author assert_equal "2010-09-18 19:59:46".to_time, last_rev.time end + + 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 "Git test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end From cad0356322c5c2a5b70ae47ba0a02320f6020146 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 07:04:29 +0000 Subject: [PATCH 009/440] scm: mercurial: add new method 'hg' to wrap shellout (#4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4830 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 58e9a269..ea022c33 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -29,6 +29,9 @@ module Redmine TEMPLATE_NAME = "hg-template" TEMPLATE_EXTENSION = "tmpl" + # raised if hg command exited with error, e.g. unknown revision. + class HgCommandAborted < CommandFailed; end + class << self def client_command @@bin ||= HG_BIN @@ -226,6 +229,20 @@ module Redmine end end + # Runs 'hg' command with the given args + def hg(*args, &block) + full_args = [HG_BIN, '--cwd', url, '--encoding', 'utf-8'] + full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}" + full_args << '--config' << 'diff.git=false' + full_args += args + ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block) + if $? && $?.exitstatus != 0 + raise HgCommandAborted, "hg exited with non-zero status: #{$?.exitstatus}" + end + ret + end + private :hg + # Returns correct revision identifier def hgrev(identifier, sq=false) rev = identifier.blank? ? 'tip' : identifier.to_s From 6d8fe71a73e5d4851666df5356ab0791ae69479c Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 07:04:49 +0000 Subject: [PATCH 010/440] scm: bazaar: add methods of getting bazaar version and add unit lib test (#4273). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4831 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/bazaar_adapter.rb | 19 +++++++++++++++++++ .../scm/adapters/bazaar_adapter_test.rb | 18 +++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/bazaar_adapter.rb b/lib/redmine/scm/adapters/bazaar_adapter.rb index 1a11f639..8bfa2bf2 100644 --- a/lib/redmine/scm/adapters/bazaar_adapter.rb +++ b/lib/redmine/scm/adapters/bazaar_adapter.rb @@ -33,6 +33,25 @@ module Redmine def sq_bin @@sq_bin ||= shell_quote(BZR_BIN) end + + def client_version + @@client_version ||= (scm_command_version || []) + end + + def client_available + !client_version.empty? + end + + def scm_command_version + scm_version = scm_version_from_command_line + if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) + m[2].scan(%r{\d+}).collect(&:to_i) + end + end + + def scm_version_from_command_line + shellout("#{sq_bin} --version") { |io| io.read }.to_s + end end # Get info about the repository 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 82372bbb..6be6b963 100644 --- a/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb @@ -5,12 +5,28 @@ begin class BazaarAdapterTest < ActiveSupport::TestCase REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/bazaar_repository' + REPOSITORY_PATH.gsub!(/\/+/, '/') if File.directory?(REPOSITORY_PATH) def setup - @adapter = Redmine::Scm::Adapters::BazaarAdapter.new(MODULE_NAME, REPOSITORY_PATH) + @adapter = Redmine::Scm::Adapters::BazaarAdapter.new(REPOSITORY_PATH) 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 + + 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 From 34e013c187c5b576c7c561bdcc09f210d51ea47e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 08:04:11 +0000 Subject: [PATCH 011/440] scm: cvs: add methods of getting cvs version and add unit lib test (#4273). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4832 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/cvs_adapter.rb | 19 +++++++++++++++++++ .../redmine/scm/adapters/cvs_adapter_test.rb | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb index c3d3bf72..676f5f7c 100644 --- a/lib/redmine/scm/adapters/cvs_adapter.rb +++ b/lib/redmine/scm/adapters/cvs_adapter.rb @@ -33,6 +33,25 @@ module Redmine def sq_bin @@sq_bin ||= shell_quote(CVS_BIN) end + + def client_version + @@client_version ||= (scm_command_version || []) + end + + def client_available + !client_version.empty? + end + + def scm_command_version + scm_version = scm_version_from_command_line + if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m) + m[2].scan(%r{\d+}).collect(&:to_i) + end + end + + def scm_version_from_command_line + shellout("#{sq_bin} --version") { |io| io.read }.to_s + end end # Guidelines for the input: 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 b6b4b6ee..b6155ea3 100644 --- a/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb @@ -13,6 +13,15 @@ begin @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 + end + def test_revisions_all cnt = 0 @adapter.revisions('', nil, nil, :with_paths => true) do |revision| @@ -29,6 +38,13 @@ begin end assert_equal 2, cnt end + + 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 From aa4b38025a417a11eff348e5179f056f06eed32e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 11:04:30 +0000 Subject: [PATCH 012/440] scm: mercurial: add Mercurial helper extension (#4455). * 'rhsummary' and 'rhmanifest' for reducing the number of hg command calls. * 'rhdiff' for compatibility with Mercurial < 1.1. Also renamed TEMPLATES_DIR to HELPERS_DIR because the directory now contains templates and a helper extension. Original version was written by Alessio Franceschelli, downloaded from http://www.redmine.org/attachments/3395/overhaul.py Contributed by Alessio Franceschelli and Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4833 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/mercurial/redminehelper.py | 167 ++++++++++++++++++ lib/redmine/scm/adapters/mercurial_adapter.rb | 5 +- .../scm/adapters/mercurial_adapter_test.rb | 4 +- 3 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 lib/redmine/scm/adapters/mercurial/redminehelper.py diff --git a/lib/redmine/scm/adapters/mercurial/redminehelper.py b/lib/redmine/scm/adapters/mercurial/redminehelper.py new file mode 100644 index 00000000..a48560ce --- /dev/null +++ b/lib/redmine/scm/adapters/mercurial/redminehelper.py @@ -0,0 +1,167 @@ +# redminehelper: Redmine helper extension for Mercurial +# +# Copyright 2010 Alessio Franceschelli (alefranz.net) +# Copyright 2010-2011 Yuya Nishihara +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. +"""helper commands for Redmine to reduce the number of hg calls + +To test this extension, please try:: + + $ hg --config extensions.redminehelper=redminehelper.py rhsummary + +I/O encoding: + +:file path: urlencoded, raw string +:tag name: utf-8 +:branch name: utf-8 +:node: 12-digits (short) hex string + +Output example of rhsummary:: + + + + + + + + ... + + + +Output example of rhmanifest:: + + + + + + + ... + + ... + + + +""" +import re, time, cgi, urllib +from mercurial import cmdutil, commands, node, error + +_x = cgi.escape +_u = lambda s: cgi.escape(urllib.quote(s)) + +def _tip(ui, repo): + # see mercurial/commands.py:tip + def tiprev(): + try: + return len(repo) - 1 + except TypeError: # Mercurial < 1.1 + return repo.changelog.count() - 1 + tipctx = repo.changectx(tiprev()) + ui.write('\n' + % (tipctx.rev(), _x(node.short(tipctx.node())))) + +_SPECIAL_TAGS = ('tip',) + +def _tags(ui, repo): + # see mercurial/commands.py:tags + for t, n in reversed(repo.tagslist()): + if t in _SPECIAL_TAGS: + continue + try: + r = repo.changelog.rev(n) + except error.LookupError: + continue + ui.write('\n' + % (r, _x(node.short(n)), _x(t))) + +def _branches(ui, repo): + # see mercurial/commands.py:branches + def iterbranches(): + for t, n in repo.branchtags().iteritems(): + yield t, n, repo.changelog.rev(n) + def branchheads(branch): + try: + return repo.branchheads(branch, closed=False) + except TypeError: # Mercurial < 1.2 + return repo.branchheads(branch) + for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True): + if repo.lookup(r) in branchheads(t): + ui.write('\n' + % (r, _x(node.short(n)), _x(t))) + +def _manifest(ui, repo, path, rev): + ctx = repo.changectx(rev) + ui.write('\n' + % (ctx.rev(), _u(path))) + + known = set() + pathprefix = (path.rstrip('/') + '/').lstrip('/') + for f, n in sorted(ctx.manifest().iteritems(), key=lambda e: e[0]): + if not f.startswith(pathprefix): + continue + name = re.sub(r'/.*', '/', f[len(pathprefix):]) + if name in known: + continue + known.add(name) + + if name.endswith('/'): + ui.write('\n' + % _x(urllib.quote(name[:-1]))) + else: + fctx = repo.filectx(f, fileid=n) + tm, tzoffset = fctx.date() + ui.write('\n' + % (_u(name), fctx.rev(), _x(node.short(fctx.node())), + tm, fctx.size(), )) + + ui.write('\n') + +def rhdiff(ui, repo, *pats, **opts): + """diff repository (or selected files)""" + change = opts.pop('change', None) + if change: # add -c option for Mercurial<1.1 + base = repo.changectx(change).parents()[0].rev() + opts['rev'] = [str(base), change] + opts['nodates'] = True + return commands.diff(ui, repo, *map(urllib.unquote, pats), **opts) + +def rhmanifest(ui, repo, path='', **opts): + """output the sub-manifest of the specified directory""" + ui.write('\n') + ui.write('\n') + ui.write('\n' % _u(repo.root)) + try: + _manifest(ui, repo, urllib.unquote(path), opts.get('rev')) + finally: + ui.write('\n') + ui.write('\n') + +def rhsummary(ui, repo, **opts): + """output the summary of the repository""" + ui.write('\n') + ui.write('\n') + ui.write('\n' % _u(repo.root)) + try: + _tip(ui, repo) + _tags(ui, repo) + _branches(ui, repo) + # TODO: bookmarks in core (Mercurial>=1.8) + finally: + ui.write('\n') + ui.write('\n') + +# This extension should be compatible with Mercurial 0.9.5. +# Note that Mercurial 0.9.5 doesn't have extensions.wrapfunction(). +cmdtable = { + 'rhdiff': (rhdiff, + [('r', 'rev', [], 'revision'), + ('c', 'change', '', 'change made by revision')], + 'hg rhdiff ([-c REV] | [-r REV] ...) [FILE]...'), + 'rhmanifest': (rhmanifest, + [('r', 'rev', '', 'show the specified revision')], + 'hg rhmanifest [-r REV] [PATH]'), + 'rhsummary': (rhsummary, [], 'hg rhsummary'), +} diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index ea022c33..53ecd4ee 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -25,7 +25,8 @@ module Redmine # Mercurial executable name HG_BIN = Redmine::Configuration['scm_mercurial_command'] || "hg" - TEMPLATES_DIR = File.dirname(__FILE__) + "/mercurial" + HELPERS_DIR = File.dirname(__FILE__) + "/mercurial" + HG_HELPER_EXT = "#{HELPERS_DIR}/redminehelper.py" TEMPLATE_NAME = "hg-template" TEMPLATE_EXTENSION = "tmpl" @@ -73,7 +74,7 @@ module Redmine else ver = "0.9.5" end - "#{TEMPLATES_DIR}/#{TEMPLATE_NAME}-#{ver}.#{TEMPLATE_EXTENSION}" + "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{ver}.#{TEMPLATE_EXTENSION}" 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 bc82c562..a6fc3612 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -4,7 +4,7 @@ begin class MercurialAdapterTest < ActiveSupport::TestCase - TEMPLATES_DIR = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATES_DIR + HELPERS_DIR = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR TEMPLATE_NAME = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION @@ -149,7 +149,7 @@ begin end def test_template_path_for(version, template) - assert_equal "#{TEMPLATES_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}", + 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 From 13e0b6b9809c8474259ab995bb795580b206cdc3 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 11:04:52 +0000 Subject: [PATCH 013/440] scm: mercurial: ignore redminehelper.pyc and redminehelper.pyo for Git and Mercurial (#4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4834 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .gitignore | 2 ++ .hgignore | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 123812cc..f4461f60 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ /db/*.sqlite3 /db/schema.rb /files/* +/lib/redmine/scm/adapters/mercurial/redminehelper.pyc +/lib/redmine/scm/adapters/mercurial/redminehelper.pyo /log/*.log* /log/mongrel_debug /public/dispatch.* diff --git a/.hgignore b/.hgignore index 733faf9f..da3ed816 100644 --- a/.hgignore +++ b/.hgignore @@ -12,6 +12,8 @@ db/*.db db/*.sqlite3 db/schema.rb files/* +lib/redmine/scm/adapters/mercurial/redminehelper.pyc +lib/redmine/scm/adapters/mercurial/redminehelper.pyo log/*.log* log/mongrel_debug public/dispatch.* From e85165c84e5e779bb0538a89c95a6ae9a098337c Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 11:05:13 +0000 Subject: [PATCH 014/440] scm: cvs: set client available if cvs version above 1.12. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4835 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/cvs_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb index 676f5f7c..6ce10e38 100644 --- a/lib/redmine/scm/adapters/cvs_adapter.rb +++ b/lib/redmine/scm/adapters/cvs_adapter.rb @@ -39,7 +39,7 @@ module Redmine end def client_available - !client_version.empty? + client_version_above?([1, 12]) end def scm_command_version From 29f99eee07298919667ddb6ef622d03fbdfb2b1d Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 15 Feb 2011 11:05:33 +0000 Subject: [PATCH 015/440] scm: bazaar: move cat and annotate test from unit app test to unit lib test. Bazaar supports revision number and do not need to read database. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4836 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/bazaar_adapter_test.rb | 13 +++++++++++++ test/unit/repository_bazaar_test.rb | 19 +++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) 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 6be6b963..7945e9bc 100644 --- a/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb @@ -21,6 +21,19 @@ begin end 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_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 + private def test_scm_version_for(scm_command_version, version) diff --git a/test/unit/repository_bazaar_test.rb b/test/unit/repository_bazaar_test.rb index 5cd7da13..55d3b8a2 100644 --- a/test/unit/repository_bazaar_test.rb +++ b/test/unit/repository_bazaar_test.rb @@ -28,7 +28,7 @@ class RepositoryBazaarTest < ActiveSupport::TestCase @project = Project.find(1) assert @repository = Repository::Bazaar.create(:project => @project, :url => "file:///#{REPOSITORY_PATH}") end - + if File.directory?(REPOSITORY_PATH) def test_fetch_changesets_from_scratch @repository.fetch_changesets @@ -38,7 +38,7 @@ class RepositoryBazaarTest < ActiveSupport::TestCase assert_equal 9, @repository.changes.count assert_equal 'Initial import', @repository.changesets.find_by_revision('1').comments end - + def test_fetch_changesets_incremental @repository.fetch_changesets # Remove changesets with revision > 5 @@ -49,7 +49,7 @@ class RepositoryBazaarTest < ActiveSupport::TestCase @repository.fetch_changesets assert_equal 4, @repository.changesets.count end - + def test_entries entries = @repository.entries assert_equal 2, entries.size @@ -68,19 +68,6 @@ class RepositoryBazaarTest < ActiveSupport::TestCase assert_equal 'file', entries.last.kind assert_equal 'edit.png', entries.last.name end - - def test_cat - cat = @repository.scm.cat('directory/document.txt') - assert cat =~ /Write the contents of a file as of a given revision to standard output/ - end - - def test_annotate - annotate = @repository.scm.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 else puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end From 60f165a9fcc4d1be999a77a874c5741c9f82900f Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 01:13:49 +0000 Subject: [PATCH 016/440] scm: mercurial: add compatible test for "info" method. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4838 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../lib/redmine/scm/adapters/mercurial_adapter_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 a6fc3612..b1afed07 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -42,6 +42,16 @@ begin end end + def test_info + [REPOSITORY_PATH, REPOSITORY_PATH + "/", + REPOSITORY_PATH + "//"].each do |repo| + adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo) + assert_equal REPOSITORY_PATH, adp.info.root_url + # assert_equal '16', adp.info.lastrev.revision + assert_equal '4cddb4e45f52',adp.info.lastrev.scmid + end + end + def test_diff if @adapter.class.client_version_above?([1, 2]) assert_nil @adapter.diff(nil, '100000') From 3f80b8a9a77212b34ca69a016ec7a0b137306c98 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 01:14:10 +0000 Subject: [PATCH 017/440] scm: mercurial: change "--cwd" option to "-R" for running "hg" (#4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4839 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 53ecd4ee..17afa674 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -232,7 +232,7 @@ module Redmine # Runs 'hg' command with the given args def hg(*args, &block) - full_args = [HG_BIN, '--cwd', url, '--encoding', 'utf-8'] + full_args = [HG_BIN, '-R', root_url, '--encoding', 'utf-8'] full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}" full_args << '--config' << 'diff.git=false' full_args += args From 357ddfb112179b00b0dec73884f3a604c0264ba5 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 01:14:34 +0000 Subject: [PATCH 018/440] scm: mercurial: add "hgtarget" method (#4455). Abstract adapter shell quotes paths. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4840 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 17afa674..c0b879a9 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -251,6 +251,12 @@ module Redmine rev end private :hgrev + + def hgtarget(path) + path ||= '' + root_url + '/' + without_leading_slash(path) + end + private :hgtarget end end end From 713757cc8c133b4422c760ac16d56aa4b29f4a6a Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 01:14:54 +0000 Subject: [PATCH 019/440] scm: mercurial: refactor "annotate" by using hg helper method (#4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4841 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index c0b879a9..04680f10 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -205,13 +205,8 @@ module Redmine end def annotate(path, identifier=nil) - path ||= '' - cmd = "#{self.class.sq_bin} -R #{target('')}" - cmd << " annotate -ncu" - cmd << " -r #{hgrev(identifier, true)}" - cmd << " #{target(path)}" blame = Annotate.new - shellout(cmd) do |io| + hg 'annotate', '-ncu', '-r', hgrev(identifier), hgtarget(path) do |io| io.each_line do |line| next unless line =~ %r{^([^:]+)\s(\d+)\s([0-9a-f]+):\s(.*)$} r = Revision.new(:author => $1.strip, :revision => $2, :scmid => $3, @@ -219,8 +214,9 @@ module Redmine blame.add_line($4.rstrip, r) end end - return nil if $? && $?.exitstatus != 0 blame + rescue HgCommandAborted + nil # means not found or cannot be annotated end class Revision < Redmine::Scm::Adapters::Revision From bed219927dca8805386ffa21ab49cbf92458d244 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 03:47:05 +0000 Subject: [PATCH 020/440] scm: mercurial: refactor "cat" by using hg helper method (#4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4842 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 04680f10..4aa3024d 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -192,16 +192,12 @@ module Redmine end def cat(path, identifier=nil) - cmd = "#{self.class.sq_bin} -R #{target('')} cat" - cmd << " -r #{hgrev(identifier, true)}" - cmd << " #{target(path)}" - cat = nil - shellout(cmd) do |io| + hg 'cat', '-r', hgrev(identifier), hgtarget(path) do |io| io.binmode - cat = io.read + io.read end - return nil if $? && $?.exitstatus != 0 - cat + rescue HgCommandAborted + nil # means not found end def annotate(path, identifier=nil) From f777cc1ee85cd550e7981b37cfd3f76cef3919bf Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 03:47:27 +0000 Subject: [PATCH 021/440] scm: mercurial: add compatible test for "revisions" method. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4843 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../redmine/scm/adapters/mercurial_adapter_test.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 b1afed07..ecf0f355 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -52,6 +52,20 @@ begin end end + def test_revisions + revisions = @adapter.revisions(nil, 2, 4) + assert_equal 3, revisions.size + # assert_equal '2', revisions[0].revision + assert_equal '400bb8672109', revisions[0].scmid + # assert_equal '4', revisions[2].revision + assert_equal 'def6d2f1254a', revisions[2].scmid + + revisions = @adapter.revisions(nil, 2, 4, {:limit => 2}) + assert_equal 2, revisions.size + # assert_equal '2', revisions[0].revision + assert_equal '400bb8672109', revisions[0].scmid + end + def test_diff if @adapter.class.client_version_above?([1, 2]) assert_nil @adapter.diff(nil, '100000') From 40ef1dd792cf7c32681611489a0a5eb644f70ae2 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 04:40:42 +0000 Subject: [PATCH 022/440] scm: mercurial: switch root_url or url in "hg" method (#4455). "info" sets root_url from url. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4844 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 4aa3024d..0cfcf4c8 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -224,7 +224,8 @@ module Redmine # Runs 'hg' command with the given args def hg(*args, &block) - full_args = [HG_BIN, '-R', root_url, '--encoding', 'utf-8'] + repo_path = root_url || url + full_args = [HG_BIN, '-R', repo_path, '--encoding', 'utf-8'] full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}" full_args << '--config' << 'diff.git=false' full_args += args From 40d72c354a7cd6a9031fcb9c5b19896aa109e1de Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 04:41:10 +0000 Subject: [PATCH 023/440] scm: mercurial: add "summary" method in adapter (#4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4845 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 0cfcf4c8..6024a52a 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -93,6 +93,13 @@ module Redmine return nil end + def summary + @summary ||= hg 'rhsummary' do |io| + ActiveSupport::XmlMini.parse(io.read)['rhsummary'] + end + end + private :summary + def entries(path=nil, identifier=nil) path ||= '' entries = Entries.new From 608025fd046ed6ef107dd9ba8ccfdbe94f5d144c Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 04:41:30 +0000 Subject: [PATCH 024/440] scm: mercurial: rewrite MercurialAdapter#info by using helper extention (#4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4846 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 16 ++++------------ .../scm/adapters/mercurial_adapter_test.rb | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 6024a52a..a1b9ca54 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -79,18 +79,10 @@ module Redmine end def info - cmd = "#{self.class.sq_bin} -R #{target('')} root" - root_url = nil - shellout(cmd) do |io| - root_url = io.read - end - return nil if $? && $?.exitstatus != 0 - info = Info.new({:root_url => root_url.chomp, - :lastrev => revisions(nil,nil,nil,{:limit => 1}).last - }) - info - rescue CommandFailed - return nil + tip = summary['repository']['tip'] + Info.new(:root_url => CGI.unescape(summary['repository']['root']), + :lastrev => Revision.new(:revision => tip['revision'], + :scmid => tip['node'])) end def summary 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 ecf0f355..3d070345 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -47,7 +47,7 @@ begin REPOSITORY_PATH + "//"].each do |repo| adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo) assert_equal REPOSITORY_PATH, adp.info.root_url - # assert_equal '16', adp.info.lastrev.revision + assert_equal '16', adp.info.lastrev.revision assert_equal '4cddb4e45f52',adp.info.lastrev.scmid end end From 33f1436eb2e9aa10a21387d6eda1e6f921900a36 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 07:31:52 +0000 Subject: [PATCH 025/440] scm: mercurial: change identifier to revision in fetching revisions. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4847 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/mercurial.rb | 2 +- lib/redmine/scm/adapters/mercurial_adapter.rb | 4 ++-- .../unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index 557b9a4d..fe208e4d 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -112,7 +112,7 @@ class Repository::Mercurial < Repository transaction do revisions.each do |revision| changeset = Changeset.create(:repository => self, - :revision => revision.identifier, + :revision => revision.revision, :scmid => revision.scmid, :committer => revision.author, :committed_on => revision.time, diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index a1b9ca54..620184b2 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -150,12 +150,12 @@ module Redmine end paths.sort! { |x,y| x[:path] <=> y[:path] } - revisions << Revision.new({:identifier => logentry.attributes['revision'], + revisions << Revision.new({:revision => logentry.attributes['revision'], :scmid => logentry.attributes['node'], :author => (logentry.elements['author'] ? logentry.elements['author'].text : ""), :time => Time.parse(logentry.elements['date'].text).localtime, :message => logentry.elements['msg'].text, - :paths => paths + :paths => paths, }) end rescue 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 3d070345..dd849272 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -55,14 +55,14 @@ begin def test_revisions revisions = @adapter.revisions(nil, 2, 4) assert_equal 3, revisions.size - # assert_equal '2', revisions[0].revision + assert_equal '2', revisions[0].revision assert_equal '400bb8672109', revisions[0].scmid - # assert_equal '4', revisions[2].revision + assert_equal '4', revisions[2].revision assert_equal 'def6d2f1254a', revisions[2].scmid revisions = @adapter.revisions(nil, 2, 4, {:limit => 2}) assert_equal 2, revisions.size - # assert_equal '2', revisions[0].revision + assert_equal '2', revisions[0].revision assert_equal '400bb8672109', revisions[0].scmid end From 0f1c932f359ceac9958e19b9acc3921cfd1f01c5 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 07:32:13 +0000 Subject: [PATCH 026/440] scm: mercurial: rewrite MercurialAdapter#revisions as an iterator (#4455). Now it uses XmlMini.parse() in place of slow REXML. Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4848 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 88 +++++++++---------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 620184b2..9092e157 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -117,53 +117,45 @@ module Redmine entries.sort_by_name end - # Fetch the revisions by using a template file that - # makes Mercurial produce a xml output. - def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) - revisions = Revisions.new - cmd = "#{self.class.sq_bin} --debug --encoding utf8 -R #{target('')} log -C --style #{shell_quote self.class.template_path}" - if identifier_from && identifier_to - cmd << " -r #{hgrev(identifier_from, true)}:#{hgrev(identifier_to, true)}" - elsif identifier_from - cmd << " -r #{hgrev(identifier_from, true)}:" - end - cmd << " --limit #{options[:limit].to_i}" if options[:limit] - cmd << " #{shell_quote path}" unless path.blank? - shellout(cmd) do |io| - begin - # HG doesn't close the XML Document... - doc = REXML::Document.new(io.read << "") - doc.elements.each("log/logentry") do |logentry| - paths = [] - copies = logentry.get_elements('paths/path-copied') - logentry.elements.each("paths/path") do |path| - # Detect if the added file is a copy - if path.attributes['action'] == 'A' and c = copies.find{ |e| e.text == path.text } - from_path = c.attributes['copyfrom-path'] - from_rev = logentry.attributes['revision'] - end - paths << {:action => path.attributes['action'], - :path => "/#{CGI.unescape(path.text)}", - :from_path => from_path ? "/#{CGI.unescape(from_path)}" : nil, - :from_revision => from_rev ? from_rev : nil - } - end - paths.sort! { |x,y| x[:path] <=> y[:path] } + def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) + revs = Revisions.new + each_revision(path, identifier_from, identifier_to, options) { |e| revs << e } + revs + end - revisions << Revision.new({:revision => logentry.attributes['revision'], - :scmid => logentry.attributes['node'], - :author => (logentry.elements['author'] ? logentry.elements['author'].text : ""), - :time => Time.parse(logentry.elements['date'].text).localtime, - :message => logentry.elements['msg'].text, - :paths => paths, - }) - end - rescue - logger.debug($!) - end + # Iterates the revisions by using a template file that + # makes Mercurial produce a xml output. + def each_revision(path=nil, identifier_from=nil, identifier_to=nil, options={}) + hg_args = ['log', '--debug', '-C', '--style', self.class.template_path] + hg_args << '-r' << "#{hgrev(identifier_from)}:#{hgrev(identifier_to)}" + hg_args << '--limit' << options[:limit] if options[:limit] + hg_args << hgtarget(path) unless path.blank? + log = hg(*hg_args) do |io| + # Mercurial < 1.5 does not support footer template for '' + ActiveSupport::XmlMini.parse("#{io.read}")['log'] end - return nil if $? && $?.exitstatus != 0 - revisions + + as_ary(log['logentry']).each do |le| + cpalist = as_ary(le['paths']['path-copied']).map do |e| + [e['__content__'], e['copyfrom-path']].map { |s| CGI.unescape(s) } + end + cpmap = Hash[*cpalist.flatten] + + paths = as_ary(le['paths']['path']).map do |e| + p = CGI.unescape(e['__content__']) + {:action => e['action'], :path => with_leading_slash(p), + :from_path => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil), + :from_revision => (cpmap.member?(p) ? le['revision'] : nil)} + end.sort { |a, b| a[:path] <=> b[:path] } + + yield Revision.new(:revision => le['revision'], + :scmid => le['node'], + :author => (le['author']['__content__'] rescue ''), + :time => Time.parse(le['date']['__content__']).localtime, + :message => le['msg']['__content__'], + :paths => paths) + end + self end def diff(path, identifier_from, identifier_to=nil) @@ -249,6 +241,12 @@ module Redmine root_url + '/' + without_leading_slash(path) end private :hgtarget + + def as_ary(o) + return [] unless o + o.is_a?(Array) ? o : Array[o] + end + private :as_ary end end end From de7f88c5727309a600f8afeae21d464fc5fbdb85 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 07:32:35 +0000 Subject: [PATCH 027/440] scm: mercurial: refactor Repository::Mercurial#fetch_changesets (#4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4849 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/mercurial.rb | 48 +++++++++++------------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index fe208e4d..d8b92a0e 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -24,6 +24,8 @@ class Repository::Mercurial < Repository attr_protected :root_url validates_presence_of :url + FETCH_AT_ONCE = 100 # number of changesets to fetch at once + def self.scm_adapter_class Redmine::Scm::Adapters::MercurialAdapter end @@ -94,38 +96,24 @@ class Repository::Mercurial < Repository end def fetch_changesets - scm_info = scm.info - if scm_info - # latest revision found in database - db_revision = latest_changeset ? latest_changeset.revision.to_i : -1 - # latest revision in the repository - latest_revision = scm_info.lastrev - return if latest_revision.nil? - scm_revision = latest_revision.identifier.to_i - if db_revision < scm_revision - logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug? - identifier_from = db_revision + 1 - while (identifier_from <= scm_revision) - # loads changesets by batches of 100 - identifier_to = [identifier_from + 99, scm_revision].min - revisions = scm.revisions('', identifier_from, identifier_to, :with_paths => true) - transaction do - revisions.each do |revision| - changeset = Changeset.create(:repository => self, - :revision => revision.revision, - :scmid => revision.scmid, - :committer => revision.author, - :committed_on => revision.time, - :comments => revision.message) - - revision.paths.each do |change| - changeset.create_change(change) - end - end - end unless revisions.nil? - identifier_from = identifier_to + 1 + scm_rev = scm.info.lastrev.revision.to_i + db_rev = latest_changeset ? latest_changeset.revision.to_i : -1 + return unless db_rev < scm_rev # already up-to-date + + logger.debug "Fetching changesets for repository #{url}" if logger + (db_rev + 1).step(scm_rev, FETCH_AT_ONCE) do |i| + transaction do + scm.each_revision('', i, [i + FETCH_AT_ONCE - 1, scm_rev].min) do |re| + cs = Changeset.create(:repository => self, + :revision => re.revision, + :scmid => re.scmid, + :committer => re.author, + :committed_on => re.time, + :comments => re.message) + re.paths.each { |e| cs.create_change(e) } end end end + self end end From f0d4b2625b7703643b2a968d15ec94dcc5a79ab6 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 11:16:29 +0000 Subject: [PATCH 028/440] scm: git: change project id of unit app test from 1 to 3. Project id 1 has Subversion fixtures. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4850 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_git_test.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/unit/repository_git_test.rb b/test/unit/repository_git_test.rb index f6f3f6ed..407250c1 100644 --- a/test/unit/repository_git_test.rb +++ b/test/unit/repository_git_test.rb @@ -18,25 +18,26 @@ require File.expand_path('../../test_helper', __FILE__) class RepositoryGitTest < ActiveSupport::TestCase - fixtures :projects, :repositories, :enabled_modules, :users, :roles - + fixtures :projects, :repositories, :enabled_modules, :users, :roles + # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository' REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin? - + def setup - @project = Project.find(1) - assert @repository = Repository::Git.create(:project => @project, :url => REPOSITORY_PATH) + @project = Project.find(3) + @repository = Repository::Git.create(:project => @project, :url => REPOSITORY_PATH) + assert @repository end - + if File.directory?(REPOSITORY_PATH) def test_fetch_changesets_from_scratch @repository.fetch_changesets @repository.reload - + assert_equal 15, @repository.changesets.count assert_equal 24, @repository.changes.count - + commit = @repository.changesets.find(:first, :order => 'committed_on ASC') assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments assert_equal "jsmith ", commit.committer From cb467e3a8b4e4f606805faedc6e77143e4ba7253 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 11:16:53 +0000 Subject: [PATCH 029/440] scm: git: implement find_changeset_by_name (#7047). SQL "like" is slow. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4851 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/git.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/models/repository/git.rb b/app/models/repository/git.rb index 26cb84db..8fb6325b 100644 --- a/app/models/repository/git.rb +++ b/app/models/repository/git.rb @@ -47,6 +47,13 @@ class Repository::Git < Repository scm.tags end + def find_changeset_by_name(name) + return nil if name.nil? || name.empty? + e = changesets.find(:first, :conditions => ['revision = ?', name.to_s]) + return e if e + changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"]) + end + # With SCM's that have a sequential commit numbering, redmine is able to be # clever and only fetch changesets going forward from the most recent one # it knows about. However, with git, you never know if people have merged From 86cbaaa5d16c735fd21bd76d1139aa81f5cd6ad5 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 11:17:15 +0000 Subject: [PATCH 030/440] scm: mercurial: code clean up unit app test. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4852 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_mercurial_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index 7523cfe9..1563820c 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -22,17 +22,17 @@ class RepositoryMercurialTest < ActiveSupport::TestCase # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository' - + def setup @project = Project.find(1) - assert @repository = Repository::Mercurial.create(:project => @project, :url => REPOSITORY_PATH) + @repository = Repository::Mercurial.create(:project => @project, :url => REPOSITORY_PATH) + assert @repository end if File.directory?(REPOSITORY_PATH) def test_fetch_changesets_from_scratch @repository.fetch_changesets @repository.reload - assert_equal 17, @repository.changesets.count assert_equal 25, @repository.changes.count assert_equal "Initial import.\nThe repository contains 3 files.", From 6840897f38d1b017a513283c6bb25221e3af59c4 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 11:17:37 +0000 Subject: [PATCH 031/440] scm: mercurial: add instance value flag of whether "hg diff -c" supports at tests (#7518). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4853 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/functional/repositories_mercurial_controller_test.rb | 3 ++- test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/functional/repositories_mercurial_controller_test.rb b/test/functional/repositories_mercurial_controller_test.rb index ae7f4226..21908282 100644 --- a/test/functional/repositories_mercurial_controller_test.rb +++ b/test/functional/repositories_mercurial_controller_test.rb @@ -34,6 +34,7 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase User.current = nil @repository = Repository::Mercurial.create(:project => Project.find(3), :url => REPOSITORY_PATH) assert @repository + @diff_c_support = @repository.scm.class.client_version_above?([1, 2]) end if File.directory?(REPOSITORY_PATH) @@ -137,7 +138,7 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase assert_response :success assert_template 'diff' - if @repository.scm.class.client_version_above?([1, 2]) + if @diff_c_support # Line 22 removed assert_tag :tag => 'th', :content => '22', 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 dd849272..e38c31ab 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -13,6 +13,7 @@ begin if File.directory?(REPOSITORY_PATH) def setup @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(REPOSITORY_PATH) + @diff_c_support = @adapter.class.client_version_above?([1, 2]) end def test_hgversion @@ -73,7 +74,7 @@ begin assert_nil @adapter.diff(nil, '100000', '200000') [2, '400bb8672109', '400', 400].each do |r1| diff1 = @adapter.diff(nil, r1) - if @adapter.class.client_version_above?([1, 2]) + 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 @@ -94,7 +95,7 @@ begin end def test_diff_made_by_revision - if @adapter.class.client_version_above?([1, 2]) + if @diff_c_support [16, '16', '4cddb4e45f52'].each do |r1| diff1 = @adapter.diff(nil, r1) assert_equal 5, diff1.size From cb26f0adf9866c84f08928df7e3f71c4c6d53c8e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 11:17:58 +0000 Subject: [PATCH 032/440] scm: mercurial: rewrite MercurialAdapter#diff by using helper extension (#4455, #7518). fix incompatibility of diff with Mercurial < 1.1. Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4854 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 9092e157..93cfcf62 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -159,27 +159,19 @@ module Redmine end def diff(path, identifier_from, identifier_to=nil) - path ||= '' - diff_args = '' - diff = [] + hg_args = %w|rhdiff| if identifier_to - diff_args = "-r #{hgrev(identifier_to, true)} -r #{hgrev(identifier_from, true)}" + hg_args << '-r' << hgrev(identifier_to) << '-r' << hgrev(identifier_from) else - if self.class.client_version_above?([1, 2]) - diff_args = "-c #{hgrev(identifier_from, true)}" - else - return [] - end + hg_args << '-c' << hgrev(identifier_from) end - cmd = "#{self.class.sq_bin} -R #{target('')} --config diff.git=false diff --nodates #{diff_args}" - cmd << " -I #{target(path)}" unless path.empty? - shellout(cmd) do |io| - io.each_line do |line| - diff << line - end + hg_args << CGI.escape(hgtarget(path)) unless path.blank? + + hg *hg_args do |io| + io.collect end - return nil if $? && $?.exitstatus != 0 - diff + rescue HgCommandAborted + nil # means not found end def cat(path, identifier=nil) From 29f9fbd2ee2249f41acd564be17b93ff02ae442d Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 11:18:18 +0000 Subject: [PATCH 033/440] scm: mercurial: set instance value flag of whether "hg diff -c" supports true at tests (#7518). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4855 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/functional/repositories_mercurial_controller_test.rb | 2 +- test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/repositories_mercurial_controller_test.rb b/test/functional/repositories_mercurial_controller_test.rb index 21908282..f784d049 100644 --- a/test/functional/repositories_mercurial_controller_test.rb +++ b/test/functional/repositories_mercurial_controller_test.rb @@ -34,7 +34,7 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase User.current = nil @repository = Repository::Mercurial.create(:project => Project.find(3), :url => REPOSITORY_PATH) assert @repository - @diff_c_support = @repository.scm.class.client_version_above?([1, 2]) + @diff_c_support = true end if File.directory?(REPOSITORY_PATH) 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 e38c31ab..d2202f73 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -13,7 +13,7 @@ begin if File.directory?(REPOSITORY_PATH) def setup @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(REPOSITORY_PATH) - @diff_c_support = @adapter.class.client_version_above?([1, 2]) + @diff_c_support = true end def test_hgversion From 3ba56db935c1b14611fdf87fe7ef8a7f69e68f61 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 13:35:52 +0000 Subject: [PATCH 034/440] scm: mercurial: rewrite MercurialAdapter#entries to show per-file change log and size (#3421, #4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4856 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/mercurial.rb | 23 ---------- lib/redmine/scm/adapters/mercurial_adapter.rb | 45 ++++++++++--------- 2 files changed, 24 insertions(+), 44 deletions(-) diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index d8b92a0e..4ee76f44 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -48,29 +48,6 @@ class Repository::Mercurial < Repository super(cs, cs_to, ' ') end - def entries(path=nil, identifier=nil) - entries=scm.entries(path, identifier) - if entries - entries.each do |entry| - next unless entry.is_file? - # Set the filesize unless browsing a specific revision - if identifier.nil? - full_path = File.join(root_url, entry.path) - entry.size = File.stat(full_path).size if File.file?(full_path) - end - # Search the DB for the entry's last change - change = changes.find(:first, :conditions => ["path = ?", scm.with_leading_slash(entry.path)], :order => "#{Changeset.table_name}.committed_on DESC") - if change - entry.lastrev.identifier = change.changeset.revision - entry.lastrev.name = change.changeset.revision - entry.lastrev.author = change.changeset.committer - entry.lastrev.revision = change.revision - end - end - end - entries - end - # Finds and returns a revision with a number or the beginning of a hash def find_changeset_by_name(name) return nil if name.nil? || name.empty? diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 93cfcf62..d64e6f8f 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -93,28 +93,31 @@ module Redmine private :summary def entries(path=nil, identifier=nil) - path ||= '' - entries = Entries.new - cmd = "#{self.class.sq_bin} -R #{target('')} --cwd #{target('')} locate" - cmd << " -r #{hgrev(identifier, true)}" - cmd << " " + shell_quote("path:#{path}") unless path.empty? - shellout(cmd) do |io| - io.each_line do |line| - # HG uses antislashs as separator on Windows - line = line.gsub(/\\/, "/") - if path.empty? or e = line.gsub!(%r{^#{with_trailling_slash(path)}},'') - e ||= line - e = e.chomp.split(%r{[\/\\]}) - entries << Entry.new({:name => e.first, - :path => (path.nil? or path.empty? ? e.first : "#{with_trailling_slash(path)}#{e.first}"), - :kind => (e.size > 1 ? 'dir' : 'file'), - :lastrev => Revision.new - }) unless e.empty? || entries.detect{|entry| entry.name == e.first} - end - end + manifest = hg('rhmanifest', '-r', hgrev(identifier), + CGI.escape(without_leading_slash(path.to_s))) do |io| + ActiveSupport::XmlMini.parse(io.read)['rhmanifest']['repository']['manifest'] end - return nil if $? && $?.exitstatus != 0 - entries.sort_by_name + path_prefix = path.blank? ? '' : with_trailling_slash(path) + + entries = Entries.new + as_ary(manifest['dir']).each do |e| + n = CGI.unescape(e['name']) + p = "#{path_prefix}#{n}" + entries << Entry.new(:name => n, :path => p, :kind => 'dir') + end + + as_ary(manifest['file']).each do |e| + n = CGI.unescape(e['name']) + p = "#{path_prefix}#{n}" + lr = Revision.new(:revision => e['revision'], :scmid => e['node'], + :time => Time.at(e['time'].to_i)) + entries << Entry.new(:name => n, :path => p, :kind => 'file', + :size => e['size'].to_i, :lastrev => lr) + end + + entries + rescue HgCommandAborted + nil # means not found end def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) From 654a22624e875f93cdb82787cd505e327e24ac32 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 15:43:15 +0000 Subject: [PATCH 035/440] scm: mercurial: add identifier to entry.lastrev (#3724, #3421). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4857 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index d64e6f8f..46f3d524 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -110,6 +110,7 @@ module Redmine n = CGI.unescape(e['name']) p = "#{path_prefix}#{n}" lr = Revision.new(:revision => e['revision'], :scmid => e['node'], + :identifier => e['node'], :time => Time.at(e['time'].to_i)) entries << Entry.new(:name => n, :path => p, :kind => 'file', :size => e['size'].to_i, :lastrev => lr) From 77f649639371cd16210929f47a3f1594d143e2db Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 15:43:36 +0000 Subject: [PATCH 036/440] scm: in repository tree, use find_changeset_by_name instead of changesets.find_by_revision (#3724, #3421). Mercurial revision numbers are far too brittle. Please see #6681 description. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4858 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/repositories/_dir_list_content.rhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/repositories/_dir_list_content.rhtml b/app/views/repositories/_dir_list_content.rhtml index 66574f1c..925dc38a 100644 --- a/app/views/repositories/_dir_list_content.rhtml +++ b/app/views/repositories/_dir_list_content.rhtml @@ -16,7 +16,7 @@ :class => (entry.is_dir? ? 'icon icon-folder' : "icon icon-file #{Redmine::MimeType.css_class_of(entry.name)}")%> <%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %> -<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %> +<% changeset = @project.repository.find_changeset_by_name(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %> <%= link_to_revision(changeset, @project) if changeset %> <%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %> <%= changeset.nil? ? h(entry.lastrev.author.to_s.split('<').first) : changeset.author if entry.lastrev %> From 7934e32ee107e2861ef6a5c5c26d4f20de02da1e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 16:06:24 +0000 Subject: [PATCH 037/440] scm: mercurial: fix Ruby 1.9 "hg diff" test fails (#7518). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4859 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 46f3d524..28f55157 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -170,10 +170,13 @@ module Redmine hg_args << '-c' << hgrev(identifier_from) end hg_args << CGI.escape(hgtarget(path)) unless path.blank? - + diff = [] hg *hg_args do |io| - io.collect + io.each_line do |line| + diff << line + end end + diff rescue HgCommandAborted nil # means not found end From 49fde3723bcadcbc9716eba980fef6be23ac269e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Thu, 17 Feb 2011 14:17:04 +0000 Subject: [PATCH 038/440] scm: fix diff revision param validation. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4860 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/repositories_controller.rb | 2 +- test/functional/repositories_subversion_controller_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index de44f1d0..ecf90084 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -218,7 +218,7 @@ class RepositoriesController < ApplicationController @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip @rev_to = params[:rev_to] - unless @rev.to_s.match(REV_PARAM_RE) && @rev.to_s.match(REV_PARAM_RE) + unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE) if @repository.branches.blank? raise InvalidRevisionParam end diff --git a/test/functional/repositories_subversion_controller_test.rb b/test/functional/repositories_subversion_controller_test.rb index be2b6087..54cc4cd6 100644 --- a/test/functional/repositories_subversion_controller_test.rb +++ b/test/functional/repositories_subversion_controller_test.rb @@ -172,6 +172,12 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase assert_error_tag :content => /was not found/ end + def test_invalid_revision_diff + get :diff, :id => 1, :rev => '1', :rev_to => 'something_weird' + assert_response 404 + assert_error_tag :content => /was not found/ + end + def test_empty_revision ['', ' ', nil].each do |r| get :revision, :id => 1, :rev => r From 2ddd6e2252bd8a83f5f4686c560262fa1d437b9a Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 00:57:43 +0000 Subject: [PATCH 039/440] scm: space cleanup of lib/redmine/scm/adapters/abstract_adapter.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4861 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/abstract_adapter.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/redmine/scm/adapters/abstract_adapter.rb b/lib/redmine/scm/adapters/abstract_adapter.rb index 3442276b..92af1944 100644 --- a/lib/redmine/scm/adapters/abstract_adapter.rb +++ b/lib/redmine/scm/adapters/abstract_adapter.rb @@ -19,10 +19,10 @@ require 'cgi' module Redmine module Scm - module Adapters + module Adapters class CommandFailed < StandardError #:nodoc: end - + class AbstractAdapter #:nodoc: class << self def client_command @@ -188,11 +188,11 @@ module Redmine def shellout(cmd, &block) self.class.shellout(cmd, &block) end - + def self.logger RAILS_DEFAULT_LOGGER end - + def self.shellout(cmd, &block) logger.debug "Shelling out: #{strip_credential(cmd)}" if logger && logger.debug? if Rails.env == 'development' @@ -210,8 +210,8 @@ module Redmine logger.error("SCM command failed, make sure that your SCM binary (eg. svn) is in PATH (#{ENV['PATH']}): #{strip_credential(cmd)}\n with: #{msg}") raise CommandFailed.new(msg) end - end - + end + # Hides username/password in a given command def self.strip_credential(cmd) q = (Redmine::Platform.mswin? ? '"' : "'") @@ -231,7 +231,7 @@ module Redmine else x.kind <=> y.kind end - } + } end def revisions @@ -329,7 +329,7 @@ module Redmine end end end - + class Annotate attr_reader :lines, :revisions From 9d9c0716f22a841b7ba4bbf3c6065d01d9781e7e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 00:58:08 +0000 Subject: [PATCH 040/440] scm: mercurial: fix unit lib test_info test fails on Windows. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4862 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 d2202f73..36b61061 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -47,7 +47,8 @@ begin [REPOSITORY_PATH, REPOSITORY_PATH + "/", REPOSITORY_PATH + "//"].each do |repo| adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo) - assert_equal REPOSITORY_PATH, adp.info.root_url + repo_path = adp.info.root_url.gsub(/\\/, "/") + assert_equal REPOSITORY_PATH, repo_path assert_equal '16', adp.info.lastrev.revision assert_equal '4cddb4e45f52',adp.info.lastrev.scmid end From 2fe248917cc52110445d822ceede8149ff2dce82 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 04:13:17 +0000 Subject: [PATCH 041/440] scm: mercurial: move entries unit test from app to lib. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4863 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../redmine/scm/adapters/mercurial_adapter_test.rb | 10 ++++++++++ test/unit/repository_mercurial_test.rb | 13 ------------- 2 files changed, 10 insertions(+), 13 deletions(-) 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 36b61061..4bc0d79d 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -133,6 +133,10 @@ begin # TODO filesize etc. 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 @@ -156,6 +160,12 @@ begin 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_access_by_nodeid path = 'sources/welcome_controller.rb' assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400bb8672109') diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index 1563820c..49bbe7ce 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -50,19 +50,6 @@ class RepositoryMercurialTest < ActiveSupport::TestCase assert_equal 17, @repository.changesets.count end - def test_entries - assert_equal 2, @repository.entries("sources", 2).size - assert_equal 2, @repository.entries("sources", '400bb8672109').size - assert_equal 1, @repository.entries("sources", 3).size - assert_equal 1, @repository.entries("sources", 'b3a615152df8').size - end - - def test_locate_on_outdated_repository - assert_equal 1, @repository.entries("images", 0).size - assert_equal 2, @repository.entries("images").size - assert_equal 2, @repository.entries("images", 2).size - end - def test_isodatesec # Template keyword 'isodatesec' supported in Mercurial 1.0 and higher if @repository.scm.class.client_version_above?([1, 0]) From e37fcfece1148f9204d09e06e75b22df448f5aca Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 04:13:40 +0000 Subject: [PATCH 042/440] scm: mercurial: unit lib test for entries (#3421). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4864 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../redmine/scm/adapters/mercurial_adapter_test.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) 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 4bc0d79d..b575812f 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -144,9 +144,15 @@ begin assert_equal 'sources', entries1[1].name assert_equal 'sources', entries1[1].path assert_equal 'dir', entries1[1].kind - assert_equal 'README', entries1[2].name - assert_equal 'README', entries1[2].path - assert_equal 'file', entries1[2].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 '9d5b5b004199', 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 From 229c237e7e85c680cf84b8b3088249f4995e28f0 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 04:20:40 +0000 Subject: [PATCH 043/440] scm: mercurial: remove "TODO" comment and fix indent of unit lib test. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4865 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 b575812f..ce528ea4 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -130,7 +130,6 @@ begin end end - # TODO filesize etc. def test_entries assert_nil @adapter.entries(nil, '100000') @@ -151,7 +150,7 @@ begin assert_equal 27, readme.size assert_equal '1', readme.lastrev.revision assert_equal '9d5b5b004199', readme.lastrev.identifier - # 2007-12-14 10:24:01 +0100 + # 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) From 513a2173305ed9b6e9bc681810760ba8c5786585 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 04:59:45 +0000 Subject: [PATCH 044/440] scm: mercurial: entries unit lib test for tag (#1981). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4866 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/mercurial_adapter_test.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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 ce528ea4..109552f7 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -165,6 +165,24 @@ begin end 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 '0885933ad4f6', 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_locate_on_outdated_repository assert_equal 1, @adapter.entries("images", 0).size assert_equal 2, @adapter.entries("images").size From 05c0c88840c9f10ed4da1626a45dee803dfdfdff Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 05:00:07 +0000 Subject: [PATCH 045/440] scm: mercurial: entries unit lib test for named branch (#7246). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4867 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/mercurial_adapter_test.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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 109552f7..0f478765 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -183,6 +183,24 @@ begin assert_equal Time.gm(2007, 12, 14, 9, 22, 52), readme.lastrev.time 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 'c51f5bb613cd', 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_locate_on_outdated_repository assert_equal 1, @adapter.entries("images", 0).size assert_equal 2, @adapter.entries("images").size From 7c6a205a018e2aed3be92d3757d85002745b1691 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 05:55:02 +0000 Subject: [PATCH 046/440] scm: mercurial: improvement latest_changesets without supporting tags and named branches (#4455). Based on latest-changesets-improvements-2.diff of #6159. http://www.redmine.org/attachments/4332/latest-changesets-improvements-2.diff Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4868 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/mercurial.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index 4ee76f44..d7f58fcd 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -61,14 +61,17 @@ class Repository::Mercurial < Repository end # Returns the latest changesets for +path+; sorted by revision number + # Default behavior is to search in cached changesets def latest_changesets(path, rev, limit=10) if path.blank? changesets.find(:all, :include => :user, :limit => limit) else - changes.find(:all, :include => {:changeset => :user}, - :conditions => ["path = ?", path.with_leading_slash], - :order => "#{Changeset.table_name}.id DESC", - :limit => limit).collect(&:changeset) + changesets.find(:all, :select => "DISTINCT #{Changeset.table_name}.*", + :joins => :changes, + :conditions => ["#{Change.table_name}.path = ? OR #{Change.table_name}.path LIKE ? ESCAPE ?", + path.with_leading_slash, + "#{path.with_leading_slash.gsub(/[%_\\]/) { |s| "\\#{s}" }}/%", '\\'], + :include => :user, :limit => limit) end end From c45f66c41e3f7cc26abf56aa7f3fb68c2ee80180 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 05:55:25 +0000 Subject: [PATCH 047/440] scm: mercurial: unit app test for latest_changeset. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4869 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_mercurial_test.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index 49bbe7ce..df37cf07 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -158,6 +158,27 @@ class RepositoryMercurialTest < ActiveSupport::TestCase assert c.event_title.include?('123:abc400bb8672:') assert_equal 'abc400bb8672', c.event_url[:rev] end + + def test_latest_changesets_with_limit + @repository.fetch_changesets + @repository.reload + changesets = @repository.latest_changesets('', nil, 2) + assert_equal @repository.latest_changesets('', nil)[0, 2], changesets + end + + def test_latest_changesets_with_filepath + @repository.fetch_changesets + @repository.reload + changesets = @repository.latest_changesets('README', nil) + assert_equal %w|8 6 1 0|, changesets.collect(&:revision) + end + + def test_latest_changesets_with_dirpath + @repository.fetch_changesets + @repository.reload + changesets = @repository.latest_changesets('images', nil) + assert_equal %w|1 0|, changesets.collect(&:revision) + end else puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end From 8f636b9b21df20ad38db8d3ce1dbcaa227e6b6a2 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 05:55:45 +0000 Subject: [PATCH 048/440] scm: mercurial: unit app test for latest_changesets SQL "like" special character '%' and '_'. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4870 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_mercurial_test.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index df37cf07..384ba42d 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -171,6 +171,14 @@ class RepositoryMercurialTest < ActiveSupport::TestCase @repository.reload changesets = @repository.latest_changesets('README', nil) assert_equal %w|8 6 1 0|, changesets.collect(&:revision) + + path = 'sql_escape/percent%dir/percent%file1.txt' + changesets = @repository.latest_changesets(path, nil) + assert_equal %w|11 10 9|, changesets.collect(&:revision) + + path = 'sql_escape/underscore_dir/understrike_file.txt' + changesets = @repository.latest_changesets(path, nil) + assert_equal %w|12 9|, changesets.collect(&:revision) end def test_latest_changesets_with_dirpath @@ -178,6 +186,14 @@ class RepositoryMercurialTest < ActiveSupport::TestCase @repository.reload changesets = @repository.latest_changesets('images', nil) assert_equal %w|1 0|, changesets.collect(&:revision) + + path = 'sql_escape/percent%dir' + changesets = @repository.latest_changesets(path, nil) + assert_equal %w|13 11 10 9|, changesets.collect(&:revision) + + path = 'sql_escape/underscore_dir' + changesets = @repository.latest_changesets(path, nil) + assert_equal %w|13 12 9|, changesets.collect(&:revision) end else puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!" From b2e4dbca6f68c3da56e7cfb288c020da0d8836ad Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 07:14:32 +0000 Subject: [PATCH 049/440] scm: mercurial: temporary disable tags and branches at model (#1981, #7246, #4455). Until latest_changesets supports tags and branches. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4871 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/mercurial.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index d7f58fcd..010e3ab6 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -44,6 +44,14 @@ class Repository::Mercurial < Repository changeset.scmid end + def branches + nil + end + + def tags + nil + end + def diff_format_revisions(cs, cs_to, sep=':') super(cs, cs_to, ' ') end From 0cdbec47b5805a201f376e9e7f0a43de24c34e4f Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 07:14:51 +0000 Subject: [PATCH 050/440] scm: mercurial: support tags at adapter (#1981). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4872 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 28f55157..e8531e61 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -85,6 +85,18 @@ module Redmine :scmid => tip['node'])) end + def tags + as_ary(summary['repository']['tag']).map { |e| e['name'] } + end + + # Returns map of {'tag' => 'nodeid', ...} + def tagmap + alist = as_ary(summary['repository']['tag']).map do |e| + e.values_at('name', 'node') + end + Hash[*alist.flatten] + end + def summary @summary ||= hg 'rhsummary' do |io| ActiveSupport::XmlMini.parse(io.read)['rhsummary'] From c60a9ee5c47af7be9b6ba081a84fef44ea6ae1c1 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 07:15:13 +0000 Subject: [PATCH 051/440] scm: mercurial: unit test for tags at adapter (#1981). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4873 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../lib/redmine/scm/adapters/mercurial_adapter_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 0f478765..8ce2d208 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -218,6 +218,16 @@ begin assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400') end + def test_tags + assert_equal ['tag_test.00', 'tag-init-revision'], @adapter.tags + end + + def test_tagmap + tm = { 'tag_test.00' => '6987191f453a', + 'tag-init-revision' => '0885933ad4f6' } + assert_equal tm, @adapter.tagmap + end + private def test_hgversion_for(hgversion, version) From 944293bb476a0327889bd02df029eeff86f1ae4a Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 07:15:37 +0000 Subject: [PATCH 052/440] scm: mercurial: support named branches at adapter (#7246). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4874 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index e8531e61..6903f80c 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -97,6 +97,18 @@ module Redmine Hash[*alist.flatten] end + def branches + as_ary(summary['repository']['branch']).map { |e| e['name'] } + end + + # Returns map of {'branch' => 'nodeid', ...} + def branchmap + alist = as_ary(summary['repository']['branch']).map do |e| + e.values_at('name', 'node') + end + Hash[*alist.flatten] + end + def summary @summary ||= hg 'rhsummary' do |io| ActiveSupport::XmlMini.parse(io.read)['rhsummary'] From e334d3dba932370fcf08455500b986a57f5977fc Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 07:15:58 +0000 Subject: [PATCH 053/440] scm: mercurial: unit test for named branches at adapter (#7246). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4875 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../redmine/scm/adapters/mercurial_adapter_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 8ce2d208..d275798c 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -228,6 +228,18 @@ begin assert_equal tm, @adapter.tagmap end + def test_branches + assert_equal ['default', 'branch (1)[2]&,%.-3_4', 'test-branch-00'], + @adapter.branches + end + + def test_branchmap + bm = { 'default' => '4cddb4e45f52', + 'branch (1)[2]&,%.-3_4' => '933ca60293d7', + 'test-branch-00' => '3a330eb32958' } + assert_equal bm, @adapter.branchmap + end + private def test_hgversion_for(hgversion, version) From add4b117ccf2ebca5ada7b1dea46cc91603585d5 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 12:44:43 +0000 Subject: [PATCH 054/440] scm: mercurial: fix exception operation in adapter "summary" method (#4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4876 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 6903f80c..80ad02f5 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -110,9 +110,16 @@ module Redmine end def summary - @summary ||= hg 'rhsummary' do |io| - ActiveSupport::XmlMini.parse(io.read)['rhsummary'] + return @summary if @summary + doc = nil + hg 'rhsummary' do |io| + output = io.read + begin + doc = ActiveSupport::XmlMini.parse(output)['rhsummary'] + rescue + end end + @summary = doc end private :summary From b399e1854864eecad09242661a99b21889218a5d Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 14:49:09 +0000 Subject: [PATCH 055/440] scm: mercurial: simplify fixing exception operation in adapter "summary" method (#4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4878 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 80ad02f5..1f706946 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -113,13 +113,11 @@ module Redmine return @summary if @summary doc = nil hg 'rhsummary' do |io| - output = io.read begin - doc = ActiveSupport::XmlMini.parse(output)['rhsummary'] + @summary = ActiveSupport::XmlMini.parse(io.read)['rhsummary'] rescue end end - @summary = doc end private :summary From dbdbe26f5c537e83837dfd9b31b9d83c4f7a9113 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 18 Feb 2011 14:49:31 +0000 Subject: [PATCH 056/440] scm: mercurial: fix exception operation in adapter all methods using xml and io.read (#4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4879 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 1f706946..10aac326 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -124,7 +124,10 @@ module Redmine def entries(path=nil, identifier=nil) manifest = hg('rhmanifest', '-r', hgrev(identifier), CGI.escape(without_leading_slash(path.to_s))) do |io| - ActiveSupport::XmlMini.parse(io.read)['rhmanifest']['repository']['manifest'] + begin + ActiveSupport::XmlMini.parse(io.read)['rhmanifest']['repository']['manifest'] + rescue + end end path_prefix = path.blank? ? '' : with_trailling_slash(path) @@ -164,8 +167,11 @@ module Redmine hg_args << '--limit' << options[:limit] if options[:limit] hg_args << hgtarget(path) unless path.blank? log = hg(*hg_args) do |io| - # Mercurial < 1.5 does not support footer template for '' - ActiveSupport::XmlMini.parse("#{io.read}")['log'] + begin + # Mercurial < 1.5 does not support footer template for '' + ActiveSupport::XmlMini.parse("#{io.read}")['log'] + rescue + end end as_ary(log['logentry']).each do |le| From ad66e0db4b37629e56786a6b9759ab4f9c79bd32 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 19 Feb 2011 00:56:13 +0000 Subject: [PATCH 057/440] scm: darcs: space cleanup in adapter. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4880 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/darcs_adapter.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/redmine/scm/adapters/darcs_adapter.rb b/lib/redmine/scm/adapters/darcs_adapter.rb index 4eed61e9..e46c9dbf 100644 --- a/lib/redmine/scm/adapters/darcs_adapter.rb +++ b/lib/redmine/scm/adapters/darcs_adapter.rb @@ -21,7 +21,7 @@ require 'rexml/document' module Redmine module Scm module Adapters - class DarcsAdapter < AbstractAdapter + class DarcsAdapter < AbstractAdapter # Darcs executable name DARCS_BIN = Redmine::Configuration['scm_darcs_command'] || "darcs" @@ -73,7 +73,7 @@ module Redmine if path.blank? path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' ) end - entries = Entries.new + entries = Entries.new cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --xml-output" cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier cmd << " #{shell_quote path}" @@ -164,7 +164,7 @@ module Redmine if modified_element.elements['modified_how'].text.match(/removed/) return nil end - + Entry.new({:name => element.attributes['name'], :path => path_prefix + element.attributes['name'], :kind => element.name == 'file' ? 'file' : 'dir', @@ -173,7 +173,7 @@ module Redmine :identifier => nil, :scmid => modified_element.elements['patch'].attributes['hash'] }) - }) + }) end def get_paths_for_patch(hash) From 6c6bc816543d320e8fb3d0d459cecf42e5f01f77 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 19 Feb 2011 01:11:30 +0000 Subject: [PATCH 058/440] scm: darcs: override client_available method (#4273). I forgot it. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4881 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/darcs_adapter.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/redmine/scm/adapters/darcs_adapter.rb b/lib/redmine/scm/adapters/darcs_adapter.rb index e46c9dbf..0ed7e963 100644 --- a/lib/redmine/scm/adapters/darcs_adapter.rb +++ b/lib/redmine/scm/adapters/darcs_adapter.rb @@ -38,6 +38,10 @@ module Redmine @@client_version ||= (darcs_binary_version || []) end + def client_available + !client_version.empty? + end + def darcs_binary_version darcsversion = darcs_binary_version_from_command_line if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)}) From 66662ac84b878de10d28e14f20c69859cd67a25a Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 19 Feb 2011 01:11:48 +0000 Subject: [PATCH 059/440] scm: catch exception of getting command and version in model (#4273). If command does not exist, Windows raises exception in shellout(). Linux does not raise exception. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4882 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository.rb | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index 4ddc7343..d1e3d8b2 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -177,7 +177,7 @@ class Repository < ActiveRecord::Base user end end - + # Fetches new changesets for all repositories of active projects # Can be called periodically by an external script # eg. ruby script/runner "Repository.fetch_changesets" @@ -187,12 +187,12 @@ class Repository < ActiveRecord::Base begin project.repository.fetch_changesets rescue Redmine::Scm::Adapters::CommandFailed => e - logger.error "Repository: error during fetching changesets: #{e.message}" + logger.error "scm: error during fetching changesets: #{e.message}" end end end end - + # scan changeset comments to find related and fixed issues for all repositories def self.scan_changesets_for_issue_ids find(:all).each(&:scan_changesets_for_issue_ids) @@ -218,15 +218,33 @@ class Repository < ActiveRecord::Base end def self.scm_command - self.scm_adapter_class.nil? ? "" : self.scm_adapter_class.client_command + ret = "" + begin + ret = self.scm_adapter_class.client_command if self.scm_adapter_class + rescue Redmine::Scm::Adapters::CommandFailed => e + logger.error "scm: error during get command: #{e.message}" + end + ret end def self.scm_version_string - self.scm_adapter_class.nil? ? "" : self.scm_adapter_class.client_version_string + ret = "" + begin + ret = self.scm_adapter_class.client_version_string if self.scm_adapter_class + rescue Redmine::Scm::Adapters::CommandFailed => e + logger.error "scm: error during get version string: #{e.message}" + end + ret end def self.scm_available - self.scm_adapter_class.nil? ? false : self.scm_adapter_class.client_available + ret = false + begin + ret = self.scm_adapter_class.client_available if self.scm_adapter_class + rescue Redmine::Scm::Adapters::CommandFailed => e + logger.error "scm: error during get scm available: #{e.message}" + end + ret end private From 19c89413b6f59d7cb5e716ce62e27c4b383a3681 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 19 Feb 2011 10:34:37 +0000 Subject: [PATCH 060/440] scm: mercurial: code cleanup. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4884 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 10aac326..9d29caef 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -111,7 +111,6 @@ module Redmine def summary return @summary if @summary - doc = nil hg 'rhsummary' do |io| begin @summary = ActiveSupport::XmlMini.parse(io.read)['rhsummary'] From 899a35fc8dbe727a73c581e5fccbdbcb532811f2 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sun, 20 Feb 2011 01:33:09 +0000 Subject: [PATCH 061/440] scm: git: add --no-color option to run "git --version". git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4885 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/git_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index ce46057c..f6a9b0d7 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -49,7 +49,7 @@ module Redmine end def scm_version_from_command_line - shellout("#{sq_bin} --version") { |io| io.read }.to_s + shellout("#{sq_bin} --version --no-color") { |io| io.read }.to_s end end From 90d0875a2e2a8cfb8758aea637821a30655c04c1 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sun, 20 Feb 2011 01:33:30 +0000 Subject: [PATCH 062/440] scm: git: add new method 'scm_cmd' to wrap shellout. Refer Mercurial adapter r4830. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4886 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/git_adapter.rb | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index f6a9b0d7..d23fc224 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -24,6 +24,9 @@ module Redmine # Git executable name GIT_BIN = Redmine::Configuration['scm_git_command'] || "git" + # raised if scm command exited with error, e.g. unknown revision. + class ScmCommandAborted < CommandFailed; end + class << self def client_command @@bin ||= GIT_BIN @@ -82,9 +85,9 @@ module Redmine end def default_branch - branches.include?('master') ? 'master' : branches.first + branches.include?('master') ? 'master' : branches.first end - + def entries(path=nil, identifier=nil) path ||= '' entries = Entries.new @@ -279,7 +282,7 @@ module Redmine end blame end - + def cat(path, identifier=nil) if identifier.nil? identifier = 'HEAD' @@ -300,6 +303,19 @@ module Redmine identifier[0,8] end end + + def scm_cmd(*args, &block) + repo_path = root_url || url + full_args = [GIT_BIN, '--git-dir', repo_path] + full_args += args + full_args << '--no-color' + ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block) + if $? && $?.exitstatus != 0 + raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}" + end + ret + end + private :scm_cmd end end end From c3bca3fccbf6b86f354f37c51bf0ce45d9481590 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sun, 20 Feb 2011 01:33:50 +0000 Subject: [PATCH 063/440] scm: git: fix wrong commit range in git log command on Windows (#7657). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4887 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/git_adapter.rb | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index d23fc224..73b79d5d 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -145,17 +145,18 @@ module Redmine def revisions(path, identifier_from, identifier_to, options={}) revisions = Revisions.new + cmd_args = %w|log --raw --date=iso --pretty=fuller| + cmd_args << "--reverse" if options[:reverse] + cmd_args << "--all" if options[:all] + cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit] + from_to = "" + from_to << "#{identifier_from}.." if identifier_from + from_to << "#{identifier_to}" if identifier_to + cmd_args << from_to if !from_to.empty? + cmd_args << "--since=#{options[:since].strftime("%Y-%m-%d %H:%M:%S")}" if options[:since] + cmd_args << "--" << "#{path}" if path && !path.empty? - cmd = "#{self.class.sq_bin} --git-dir #{target('')} log --no-color --raw --date=iso --pretty=fuller " - cmd << " --reverse " if options[:reverse] - cmd << " --all " if options[:all] - cmd << " -n #{options[:limit].to_i} " if options[:limit] - cmd << "#{shell_quote(identifier_from + '..')}" if identifier_from - cmd << "#{shell_quote identifier_to}" if identifier_to - cmd << " --since=#{shell_quote(options[:since].strftime("%Y-%m-%d %H:%M:%S"))}" if options[:since] - cmd << " -- #{shell_quote path}" if path && !path.empty? - - shellout(cmd) do |io| + scm_cmd *cmd_args do |io| files=[] changeset = {} parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files @@ -232,8 +233,8 @@ module Redmine end end end - - return nil if $? && $?.exitstatus != 0 + revisions + rescue ScmCommandAborted revisions end From 4a7c41d30c318465b38500ab128898c9d189a1b6 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 20 Feb 2011 13:11:10 +0000 Subject: [PATCH 064/440] Fixed: Syntax highlighting unavailable from board new topic or topic edit preview (#7625). Contributed by Etienne Massip. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4889 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/boards/show.rhtml | 1 + app/views/messages/edit.rhtml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/views/boards/show.rhtml b/app/views/boards/show.rhtml index 23e453e3..c4a08b29 100644 --- a/app/views/boards/show.rhtml +++ b/app/views/boards/show.rhtml @@ -69,4 +69,5 @@ <% content_for :header_tags do %> <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@project}: #{@board}") %> + <%= stylesheet_link_tag 'scm' %> <% end %> diff --git a/app/views/messages/edit.rhtml b/app/views/messages/edit.rhtml index 56e70862..c22b6221 100644 --- a/app/views/messages/edit.rhtml +++ b/app/views/messages/edit.rhtml @@ -12,3 +12,7 @@ }, :accesskey => accesskey(:preview) %> <% end %>
+ +<% content_for :header_tags do %> + <%= stylesheet_link_tag 'scm' %> +<% end %> From f06bb4be34e950db3e04198d34d11d682b1381ad Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 20 Feb 2011 13:13:10 +0000 Subject: [PATCH 065/440] Fixed: Workflow summary shows X icon for workflow with exactly 1 status transition (#7611). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4890 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/workflows/index.rhtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/workflows/index.rhtml b/app/views/workflows/index.rhtml index bed6a34d..21287a22 100644 --- a/app/views/workflows/index.rhtml +++ b/app/views/workflows/index.rhtml @@ -24,7 +24,7 @@ <%= h tracker %> <% roles.each do |role, count| -%> - <%= link_to((count > 1 ? count : image_tag('false.png')), {:action => 'edit', :role_id => role, :tracker_id => tracker}, :title => l(:button_edit)) %> + <%= link_to((count > 0 ? count : image_tag('false.png')), {:action => 'edit', :role_id => role, :tracker_id => tracker}, :title => l(:button_edit)) %> <% end -%> From b615e60fd88f1e4b4d3221ff064bfa2db3f838f4 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 20 Feb 2011 14:26:23 +0000 Subject: [PATCH 066/440] Do not keep illegitimate custom_values when setting custom_field_values (#7604). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4891 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- vendor/plugins/acts_as_customizable/lib/acts_as_customizable.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/plugins/acts_as_customizable/lib/acts_as_customizable.rb b/vendor/plugins/acts_as_customizable/lib/acts_as_customizable.rb index 9ed9fe37..b99c38c4 100644 --- a/vendor/plugins/acts_as_customizable/lib/acts_as_customizable.rb +++ b/vendor/plugins/acts_as_customizable/lib/acts_as_customizable.rb @@ -71,6 +71,7 @@ module Redmine custom_field_values.each do |custom_value| custom_value.value = values[custom_value.custom_field_id.to_s] if values.has_key?(custom_value.custom_field_id.to_s) end if values.is_a?(Hash) + self.custom_values = custom_field_values end def custom_field_values From 2b3ad7ab10896778ea0f4a19752a59db0994a09d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 20 Feb 2011 14:27:34 +0000 Subject: [PATCH 067/440] Use #custom_field_values to display issue custom fields in email, just like on regular views (#7604). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4892 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/mailer/_issue_text_html.rhtml | 2 +- app/views/mailer/_issue_text_plain.rhtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/mailer/_issue_text_html.rhtml b/app/views/mailer/_issue_text_html.rhtml index 3b1812d9..3d851d44 100644 --- a/app/views/mailer/_issue_text_html.rhtml +++ b/app/views/mailer/_issue_text_html.rhtml @@ -7,7 +7,7 @@
  • <%=l(:field_assigned_to)%>: <%=h issue.assigned_to %>
  • <%=l(:field_category)%>: <%=h issue.category %>
  • <%=l(:field_fixed_version)%>: <%=h issue.fixed_version %>
  • -<% issue.custom_values.each do |c| %> +<% issue.custom_field_values.each do |c| %>
  • <%=h c.custom_field.name %>: <%=h show_value(c) %>
  • <% end %> diff --git a/app/views/mailer/_issue_text_plain.rhtml b/app/views/mailer/_issue_text_plain.rhtml index 6b87c180..bea2a581 100644 --- a/app/views/mailer/_issue_text_plain.rhtml +++ b/app/views/mailer/_issue_text_plain.rhtml @@ -7,7 +7,7 @@ <%=l(:field_assigned_to)%>: <%= issue.assigned_to %> <%=l(:field_category)%>: <%= issue.category %> <%=l(:field_fixed_version)%>: <%= issue.fixed_version %> -<% issue.custom_values.each do |c| %><%= c.custom_field.name %>: <%= show_value(c) %> +<% issue.custom_field_values.each do |c| %><%= c.custom_field.name %>: <%= show_value(c) %> <% end %> <%= issue.description %> From 47fdf7bb3f08bd520e3ee4ec67b03b08ee47b4a7 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sun, 20 Feb 2011 14:49:09 +0000 Subject: [PATCH 068/440] scm: git: move "--no-color" option from scm_cmd() to revision(). Ruby 1.9.2 test fails. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4893 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/git_adapter.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index 73b79d5d..7d742235 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -145,7 +145,7 @@ module Redmine def revisions(path, identifier_from, identifier_to, options={}) revisions = Revisions.new - cmd_args = %w|log --raw --date=iso --pretty=fuller| + cmd_args = %w|log --no-color --raw --date=iso --pretty=fuller| cmd_args << "--reverse" if options[:reverse] cmd_args << "--all" if options[:all] cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit] @@ -309,7 +309,6 @@ module Redmine repo_path = root_url || url full_args = [GIT_BIN, '--git-dir', repo_path] full_args += args - full_args << '--no-color' ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block) if $? && $?.exitstatus != 0 raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}" From 93a6d6c296405f4099dbe84295f762f8aeca8532 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 20 Feb 2011 14:56:37 +0000 Subject: [PATCH 069/440] Fixed: date part of the time default format doesn't respect the date format (#7639). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4894 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/i18n.rb | 4 ++-- test/unit/lib/redmine/i18n_test.rb | 33 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/redmine/i18n.rb b/lib/redmine/i18n.rb index 1bfca81e..f0cc529b 100644 --- a/lib/redmine/i18n.rb +++ b/lib/redmine/i18n.rb @@ -45,8 +45,8 @@ module Redmine time = time.to_time if time.is_a?(String) zone = User.current.time_zone local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time) - Setting.time_format.blank? ? ::I18n.l(local, :format => (include_date ? :default : :time)) : - ((include_date ? "#{format_date(time)} " : "") + "#{local.strftime(Setting.time_format)}") + (include_date ? "#{format_date(local)} " : "") + + (Setting.time_format.blank? ? ::I18n.l(local, :format => :time) : local.strftime(Setting.time_format)) end def day_name(day) diff --git a/test/unit/lib/redmine/i18n_test.rb b/test/unit/lib/redmine/i18n_test.rb index 5bb69c9a..7ef5feb3 100644 --- a/test/unit/lib/redmine/i18n_test.rb +++ b/test/unit/lib/redmine/i18n_test.rb @@ -58,13 +58,36 @@ class Redmine::I18nTest < ActiveSupport::TestCase end end + def test_time_format + set_language_if_valid 'en' + now = Time.parse('2011-02-20 15:45:22') + with_settings :time_format => '%H:%M' do + with_settings :date_format => '' do + assert_equal '02/20/2011 15:45', format_time(now) + assert_equal '15:45', format_time(now, false) + end + + with_settings :date_format => '%Y-%m-%d' do + assert_equal '2011-02-20 15:45', format_time(now) + assert_equal '15:45', format_time(now, false) + end + end + end + def test_time_format_default set_language_if_valid 'en' - now = Time.now - Setting.date_format = '' - Setting.time_format = '' - assert_equal I18n.l(now), format_time(now) - assert_equal I18n.l(now, :format => :time), format_time(now, false) + now = Time.parse('2011-02-20 15:45:22') + with_settings :time_format => '' do + with_settings :date_format => '' do + assert_equal '02/20/2011 03:45 pm', format_time(now) + assert_equal '03:45 pm', format_time(now, false) + end + + with_settings :date_format => '%Y-%m-%d' do + assert_equal '2011-02-20 03:45 pm', format_time(now) + assert_equal '03:45 pm', format_time(now, false) + end + end end def test_time_format From cc2d6f36055e111ad1fbad1b84c5773503e73605 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 20 Feb 2011 15:38:07 +0000 Subject: [PATCH 070/440] Allow additional workflow transitions for issue author and assignee (#2732). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4895 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/workflows_controller.rb | 17 ++++- app/models/issue.rb | 7 +- app/models/issue_status.rb | 27 +++---- app/views/workflows/_form.html.erb | 40 +++++++++++ app/views/workflows/edit.rhtml | 71 +++++++------------ ...60626_add_workflows_assignee_and_author.rb | 13 ++++ public/javascripts/application.js | 6 ++ test/fixtures/issue_statuses.yml | 26 ++++--- test/functional/workflows_controller_test.rb | 44 +++++++++--- test/unit/issue_status_test.rb | 26 ++++++- test/unit/issue_test.rb | 27 +++++++ 11 files changed, 221 insertions(+), 83 deletions(-) create mode 100644 app/views/workflows/_form.html.erb create mode 100644 db/migrate/20110220160626_add_workflows_assignee_and_author.rb diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb index ed464012..9ca1a98c 100644 --- a/app/controllers/workflows_controller.rb +++ b/app/controllers/workflows_controller.rb @@ -32,14 +32,17 @@ class WorkflowsController < ApplicationController if request.post? Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id]) - (params[:issue_status] || []).each { |old, news| - news.each { |new| - @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new) + (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') + @role.workflows.build(: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 :action => 'edit', :role_id => @role, :tracker_id => @tracker + return end end @@ -48,6 +51,14 @@ class WorkflowsController < ApplicationController @statuses = @tracker.issue_statuses end @statuses ||= IssueStatus.find(:all, :order => 'position') + + if @tracker && @role && @statuses.any? + workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id}) + @workflows = {} + @workflows['always'] = workflows.select {|w| !w.author && !w.assignee} + @workflows['author'] = workflows.select {|w| w.author} + @workflows['assignee'] = workflows.select {|w| w.assignee} + end end def copy diff --git a/app/models/issue.rb b/app/models/issue.rb index 40b64f3e..2810138a 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -422,7 +422,12 @@ class Issue < ActiveRecord::Base # Returns an array of status that user is able to apply def new_statuses_allowed_to(user, include_default=false) - statuses = status.find_new_statuses_allowed_to(user.roles_for_project(project), tracker) + statuses = status.find_new_statuses_allowed_to( + user.roles_for_project(project), + tracker, + author == user, + assigned_to_id_changed? ? assigned_to_id_was == user.id : assigned_to_id == user.id + ) statuses << status unless statuses.empty? statuses << IssueStatus.default if include_default statuses = statuses.uniq.sort diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb index 8171cdb7..5527e2c9 100644 --- a/app/models/issue_status.rb +++ b/app/models/issue_status.rb @@ -50,10 +50,16 @@ class IssueStatus < ActiveRecord::Base # Returns an array of all statuses the given role can switch to # Uses association cache when called more than one time - def new_statuses_allowed_to(roles, tracker) + def new_statuses_allowed_to(roles, tracker, author=false, assignee=false) if roles && tracker role_ids = roles.collect(&:id) - new_statuses = workflows.select {|w| role_ids.include?(w.role_id) && w.tracker_id == tracker.id}.collect{|w| w.new_status}.compact.sort + transitions = workflows.select do |w| + role_ids.include?(w.role_id) && + w.tracker_id == tracker.id && + (author || !w.author) && + (assignee || !w.assignee) + end + transitions.collect{|w| w.new_status}.compact.sort else [] end @@ -61,24 +67,19 @@ class IssueStatus < ActiveRecord::Base # Same thing as above but uses a database query # More efficient than the previous method if called just once - def find_new_statuses_allowed_to(roles, tracker) + def find_new_statuses_allowed_to(roles, tracker, author=false, assignee=false) if roles && tracker + conditions = {:role_id => roles.collect(&:id), :tracker_id => tracker.id} + conditions[:author] = false unless author + conditions[:assignee] = false unless assignee + workflows.find(:all, :include => :new_status, - :conditions => { :role_id => roles.collect(&:id), - :tracker_id => tracker.id}).collect{ |w| w.new_status }.compact.sort + :conditions => conditions).collect{|w| w.new_status}.compact.sort else [] end end - - def new_status_allowed_to?(status, roles, tracker) - if status && roles && tracker - !workflows.find(:first, :conditions => {:new_status_id => status.id, :role_id => roles.collect(&:id), :tracker_id => tracker.id}).nil? - else - false - end - end def <=>(status) position <=> status.position diff --git a/app/views/workflows/_form.html.erb b/app/views/workflows/_form.html.erb new file mode 100644 index 00000000..e5b54c07 --- /dev/null +++ b/app/views/workflows/_form.html.erb @@ -0,0 +1,40 @@ + + + + + + + + + <% for new_status in @statuses %> + + <% end %> + + + + <% for old_status in @statuses %> + "> + + <% for new_status in @statuses -%> + + <% end -%> + + <% end %> + +
    + <%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('table.transitions-#{name} input')", + :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %> + <%=l(:label_current_status)%> + <%=l(:label_new_statuses_allowed)%>
    + <%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('table.transitions-#{name} input.new-status-#{new_status.id}')", + :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %> + <%=h new_status.name %> +
    + <%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('table.transitions-#{name} input.old-status-#{old_status.id}')", + :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %> + + <%=h old_status.name %> + + <%= check_box_tag "issue_status[#{ old_status.id }][#{new_status.id}][]", name, workflows.detect {|w| w.old_status_id == old_status.id && w.new_status_id == new_status.id}, + :class => "old-status-#{old_status.id} new-status-#{new_status.id}" %> +
    \ No newline at end of file diff --git a/app/views/workflows/edit.rhtml b/app/views/workflows/edit.rhtml index 26f2cf96..2a4b8be5 100644 --- a/app/views/workflows/edit.rhtml +++ b/app/views/workflows/edit.rhtml @@ -20,54 +20,31 @@

    <% end %> - <% if @tracker && @role && @statuses.any? %> -<% form_tag({}, :id => 'workflow_form' ) do %> -<%= hidden_field_tag 'tracker_id', @tracker.id %> -<%= hidden_field_tag 'role_id', @role.id %> -
    - - - - - - - - - <% for new_status in @statuses %> - - <% end %> - - - - <% for old_status in @statuses %> - "> - - <% new_status_ids_allowed = old_status.find_new_statuses_allowed_to([@role], @tracker).collect(&:id) -%> - <% for new_status in @statuses -%> - - <% end -%> - - <% end %> - -
    <%=l(:label_current_status)%><%=l(:label_new_statuses_allowed)%>
    - <%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('input.new-status-#{new_status.id}')", - :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %> - <%= new_status.name %> -
    - <%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('input.old-status-#{old_status.id}')", - :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %> - - <%= old_status.name %> - - <%= check_box_tag "issue_status[#{ old_status.id }][]", new_status.id, new_status_ids_allowed.include?(new_status.id), - :class => "old-status-#{old_status.id} new-status-#{new_status.id}" %> -
    -
    -

    <%= check_all_links 'workflow_form' %>

    - -<%= submit_tag l(:button_save) %> -<% end %> + <% form_tag({}, :id => 'workflow_form' ) do %> + <%= hidden_field_tag 'tracker_id', @tracker.id %> + <%= hidden_field_tag 'role_id', @role.id %> +
    + <%= render :partial => 'form', :locals => {:name => 'always', :workflows => @workflows['always']} %> + +
    + Autorisations supplémentaires lorsque l'utilisateur a créé la demande +
    + <%= render :partial => 'form', :locals => {:name => 'author', :workflows => @workflows['author']} %> +
    +
    + <%= javascript_tag "hideFieldset($('author_workflows'))" unless @workflows['author'].present? %> + +
    + Autorisations supplémentaires lorsque la demande est assignée à l'utilisateur +
    + <%= render :partial => 'form', :locals => {:name => 'assignee', :workflows => @workflows['assignee']} %> +
    +
    + <%= javascript_tag "hideFieldset($('assignee_workflows'))" unless @workflows['assignee'].present? %> +
    + <%= submit_tag l(:button_save) %> + <% end %> <% end %> <% html_title(l(:label_workflow)) -%> diff --git a/db/migrate/20110220160626_add_workflows_assignee_and_author.rb b/db/migrate/20110220160626_add_workflows_assignee_and_author.rb new file mode 100644 index 00000000..73ccb4e0 --- /dev/null +++ b/db/migrate/20110220160626_add_workflows_assignee_and_author.rb @@ -0,0 +1,13 @@ +class AddWorkflowsAssigneeAndAuthor < ActiveRecord::Migration + def self.up + add_column :workflows, :assignee, :boolean, :null => false, :default => false + add_column :workflows, :author, :boolean, :null => false, :default => false + Workflow.update_all("assignee = #{Workflow.connection.quoted_false}") + Workflow.update_all("author = #{Workflow.connection.quoted_false}") + end + + def self.down + remove_column :workflows, :assignee + remove_column :workflows, :author + end +end diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 26671685..4ba55814 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -46,6 +46,12 @@ function toggleFieldset(el) { Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2}); } +function hideFieldset(el) { + var fieldset = Element.up(el, 'fieldset'); + fieldset.toggleClassName('collapsed'); + fieldset.down('div').hide(); +} + var fileFieldCount = 1; function addFileField() { diff --git a/test/fixtures/issue_statuses.yml b/test/fixtures/issue_statuses.yml index 098ac961..ff40b1c5 100644 --- a/test/fixtures/issue_statuses.yml +++ b/test/fixtures/issue_statuses.yml @@ -1,31 +1,37 @@ --- -issue_statuses_006: - name: Rejected - is_default: false - is_closed: true - id: 6 issue_statuses_001: + id: 1 name: New is_default: true is_closed: false - id: 1 + position: 1 issue_statuses_002: + id: 2 name: Assigned is_default: false is_closed: false - id: 2 + position: 2 issue_statuses_003: + id: 3 name: Resolved is_default: false is_closed: false - id: 3 + position: 3 issue_statuses_004: name: Feedback + id: 4 is_default: false is_closed: false - id: 4 + position: 4 issue_statuses_005: + id: 5 name: Closed is_default: false is_closed: true - id: 5 + position: 5 +issue_statuses_006: + id: 6 + name: Rejected + is_default: false + is_closed: true + position: 6 diff --git a/test/functional/workflows_controller_test.rb b/test/functional/workflows_controller_test.rb index 64d606a8..c868e019 100644 --- a/test/functional/workflows_controller_test.rb +++ b/test/functional/workflows_controller_test.rb @@ -65,17 +65,17 @@ class WorkflowsControllerTest < ActionController::TestCase # allowed transitions assert_tag :tag => 'input', :attributes => { :type => 'checkbox', - :name => 'issue_status[3][]', - :value => '5', + :name => 'issue_status[3][5][]', + :value => 'always', :checked => 'checked' } # not allowed assert_tag :tag => 'input', :attributes => { :type => 'checkbox', - :name => 'issue_status[3][]', - :value => '2', + :name => 'issue_status[3][2][]', + :value => 'always', :checked => nil } # unused assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox', - :name => 'issue_status[4][]' } + :name => 'issue_status[1][1][]' } end def test_get_edit_with_role_and_tracker_and_all_statuses @@ -89,13 +89,17 @@ class WorkflowsControllerTest < ActionController::TestCase assert_equal IssueStatus.count, assigns(:statuses).size assert_tag :tag => 'input', :attributes => { :type => 'checkbox', - :name => 'issue_status[1][]', - :value => '1', + :name => 'issue_status[1][1][]', + :value => 'always', :checked => nil } end def test_post_edit - post :edit, :role_id => 2, :tracker_id => 1, :issue_status => {'4' => ['5'], '3' => ['1', '2']} + post :edit, :role_id => 2, :tracker_id => 1, + :issue_status => { + '4' => {'5' => ['always']}, + '3' => {'1' => ['always'], '2' => ['always']} + } assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1' assert_equal 3, Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2}) @@ -103,6 +107,30 @@ class WorkflowsControllerTest < ActionController::TestCase assert_nil Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4}) end + def test_post_edit_with_additional_transitions + post :edit, :role_id => 2, :tracker_id => 1, + :issue_status => { + '4' => {'5' => ['always']}, + '3' => {'1' => ['author'], '2' => ['assignee'], '4' => ['author', 'assignee']} + } + assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1' + + assert_equal 4, Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2}) + + w = Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 4, :new_status_id => 5}) + assert ! w.author + assert ! w.assignee + w = Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 1}) + assert w.author + assert ! w.assignee + w = Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2}) + assert ! w.author + assert w.assignee + w = Workflow.find(:first, :conditions => {:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 4}) + assert w.author + assert w.assignee + end + def test_clear_workflow assert Workflow.count(:conditions => {:tracker_id => 1, :role_id => 2}) > 0 diff --git a/test/unit/issue_status_test.rb b/test/unit/issue_status_test.rb index 4fc6de1e..bc6535ed 100644 --- a/test/unit/issue_status_test.rb +++ b/test/unit/issue_status_test.rb @@ -18,7 +18,7 @@ require File.expand_path('../../test_helper', __FILE__) class IssueStatusTest < ActiveSupport::TestCase - fixtures :issue_statuses, :issues + fixtures :issue_statuses, :issues, :roles, :trackers def test_create status = IssueStatus.new :name => "Assigned" @@ -68,6 +68,30 @@ class IssueStatusTest < ActiveSupport::TestCase status.reload assert status.is_default? end + + def test_new_statuses_allowed_to + Workflow.delete_all + + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false) + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false) + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true) + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true) + status = IssueStatus.find(1) + role = Role.find(1) + tracker = Tracker.find(1) + + assert_equal [2], status.new_statuses_allowed_to([role], tracker, false, false).map(&:id) + assert_equal [2], status.find_new_statuses_allowed_to([role], tracker, false, false).map(&:id) + + assert_equal [2, 3], status.new_statuses_allowed_to([role], tracker, true, false).map(&:id) + assert_equal [2, 3], status.find_new_statuses_allowed_to([role], tracker, true, false).map(&:id) + + assert_equal [2, 4], status.new_statuses_allowed_to([role], tracker, false, true).map(&:id) + assert_equal [2, 4], status.find_new_statuses_allowed_to([role], tracker, false, true).map(&:id) + + assert_equal [2, 3, 4, 5], status.new_statuses_allowed_to([role], tracker, true, true).map(&:id) + assert_equal [2, 3, 4, 5], status.find_new_statuses_allowed_to([role], tracker, true, true).map(&:id) + end context "#update_done_ratios" do setup do diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index d284c746..0ecfa2e4 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -210,6 +210,33 @@ class IssueTest < ActiveSupport::TestCase assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to end + + + def test_new_statuses_allowed_to + Workflow.delete_all + + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false) + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false) + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true) + Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true) + status = IssueStatus.find(1) + role = Role.find(1) + tracker = Tracker.find(1) + user = User.find(2) + + issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1) + assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id) + + issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user) + assert_equal [1, 2, 3], issue.new_statuses_allowed_to(user).map(&:id) + + issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user) + assert_equal [1, 2, 4], issue.new_statuses_allowed_to(user).map(&:id) + + issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user) + assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) + end + def test_copy issue = Issue.new.copy_from(1) assert issue.save From 748ce2772802f4d2f2a5a66a09b49a9ec38c09b1 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 21 Feb 2011 03:59:30 +0000 Subject: [PATCH 071/440] scm: subversion: change some functional tests project id from 1 to 3. TODO: remaining tests read fixture. All tests need to read test repository. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4896 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- ...repositories_subversion_controller_test.rb | 85 ++++++++++++++----- 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/test/functional/repositories_subversion_controller_test.rb b/test/functional/repositories_subversion_controller_test.rb index 54cc4cd6..7ca863d1 100644 --- a/test/functional/repositories_subversion_controller_test.rb +++ b/test/functional/repositories_subversion_controller_test.rb @@ -26,17 +26,26 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase :repositories, :issues, :issue_statuses, :changesets, :changes, :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers + PRJ_ID = 3 + def setup @controller = RepositoriesController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new Setting.default_language = 'en' User.current = nil + + @project = Project.find(PRJ_ID) + @repository = Repository::Subversion.create(:project => @project, + :url => "file://#{self.class.repository_path('subversion')}") + assert @repository end if repository_configured?('subversion') def test_show - get :show, :id => 1 + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID assert_response :success assert_template 'show' assert_not_nil assigns(:entries) @@ -44,7 +53,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_browse_root - get :show, :id => 1 + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID assert_response :success assert_template 'show' assert_not_nil assigns(:entries) @@ -53,7 +64,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_browse_directory - get :show, :id => 1, :path => ['subversion_test'] + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID, :path => ['subversion_test'] assert_response :success assert_template 'show' assert_not_nil assigns(:entries) @@ -65,7 +78,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_browse_at_given_revision - get :show, :id => 1, :path => ['subversion_test'], :rev => 4 + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID, :path => ['subversion_test'], :rev => 4 assert_response :success assert_template 'show' assert_not_nil assigns(:entries) @@ -73,7 +88,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_file_changes - get :changes, :id => 1, :path => ['subversion_test', 'folder', 'helloworld.rb' ] + @repository.fetch_changesets + @repository.reload + get :changes, :id => PRJ_ID, :path => ['subversion_test', 'folder', 'helloworld.rb' ] assert_response :success assert_template 'changes' @@ -93,7 +110,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_directory_changes - get :changes, :id => 1, :path => ['subversion_test', 'folder' ] + @repository.fetch_changesets + @repository.reload + get :changes, :id => PRJ_ID, :path => ['subversion_test', 'folder' ] assert_response :success assert_template 'changes' @@ -103,15 +122,19 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_entry - get :entry, :id => 1, :path => ['subversion_test', 'helloworld.c'] + @repository.fetch_changesets + @repository.reload + get :entry, :id => PRJ_ID, :path => ['subversion_test', 'helloworld.c'] assert_response :success assert_template 'entry' end def test_entry_should_send_if_too_big + @repository.fetch_changesets + @repository.reload # no files in the test repo is larger than 1KB... with_settings :file_max_size_displayed => 0 do - get :entry, :id => 1, :path => ['subversion_test', 'helloworld.c'] + get :entry, :id => PRJ_ID, :path => ['subversion_test', 'helloworld.c'] assert_response :success assert_template '' assert_equal 'attachment; filename="helloworld.c"', @response.headers['Content-Disposition'] @@ -119,7 +142,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_entry_at_given_revision - get :entry, :id => 1, :path => ['subversion_test', 'helloworld.rb'], :rev => 2 + @repository.fetch_changesets + @repository.reload + get :entry, :id => PRJ_ID, :path => ['subversion_test', 'helloworld.rb'], :rev => 2 assert_response :success assert_template 'entry' # this line was removed in r3 and file was moved in r6 @@ -128,27 +153,36 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_entry_not_found - get :entry, :id => 1, :path => ['subversion_test', 'zzz.c'] + @repository.fetch_changesets + @repository.reload + get :entry, :id => PRJ_ID, :path => ['subversion_test', 'zzz.c'] assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ }, :content => /The entry or revision was not found in the repository/ end def test_entry_download - get :entry, :id => 1, :path => ['subversion_test', 'helloworld.c'], :format => 'raw' + @repository.fetch_changesets + @repository.reload + get :entry, :id => PRJ_ID, :path => ['subversion_test', 'helloworld.c'], :format => 'raw' assert_response :success assert_template '' assert_equal 'attachment; filename="helloworld.c"', @response.headers['Content-Disposition'] end def test_directory_entry - get :entry, :id => 1, :path => ['subversion_test', 'folder'] + @repository.fetch_changesets + @repository.reload + get :entry, :id => PRJ_ID, :path => ['subversion_test', 'folder'] assert_response :success assert_template 'show' assert_not_nil assigns(:entry) assert_equal 'folder', assigns(:entry).name end + # TODO: this test needs fixtures. def test_revision + @repository.fetch_changesets + @repository.reload get :revision, :id => 1, :rev => 2 assert_response :success assert_template 'revision' @@ -167,25 +201,30 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_invalid_revision - get :revision, :id => 1, :rev => 'something_weird' + @repository.fetch_changesets + @repository.reload + get :revision, :id => PRJ_ID, :rev => 'something_weird' assert_response 404 assert_error_tag :content => /was not found/ end def test_invalid_revision_diff - get :diff, :id => 1, :rev => '1', :rev_to => 'something_weird' + get :diff, :id => PRJ_ID, :rev => '1', :rev_to => 'something_weird' assert_response 404 assert_error_tag :content => /was not found/ end def test_empty_revision + @repository.fetch_changesets + @repository.reload ['', ' ', nil].each do |r| - get :revision, :id => 1, :rev => r + get :revision, :id => PRJ_ID, :rev => r assert_response 404 assert_error_tag :content => /was not found/ end end + # TODO: this test needs fixtures. def test_revision_with_repository_pointing_to_a_subdirectory r = Project.find(1).repository # Changes repository url to a subdirectory @@ -209,7 +248,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_revision_diff - get :diff, :id => 1, :rev => 3 + @repository.fetch_changesets + @repository.reload + get :diff, :id => PRJ_ID, :rev => 3 assert_response :success assert_template 'diff' @@ -217,7 +258,9 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_directory_diff - get :diff, :id => 1, :rev => 6, :rev_to => 2, :path => ['subversion_test', 'folder'] + @repository.fetch_changesets + @repository.reload + get :diff, :id => PRJ_ID, :rev => 6, :rev_to => 2, :path => ['subversion_test', 'folder'] assert_response :success assert_template 'diff' @@ -230,13 +273,17 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase end def test_annotate - get :annotate, :id => 1, :path => ['subversion_test', 'helloworld.c'] + @repository.fetch_changesets + @repository.reload + get :annotate, :id => PRJ_ID, :path => ['subversion_test', 'helloworld.c'] assert_response :success assert_template 'annotate' end def test_annotate_at_given_revision - get :annotate, :id => 1, :rev => 8, :path => ['subversion_test', 'helloworld.c'] + @repository.fetch_changesets + @repository.reload + get :annotate, :id => PRJ_ID, :rev => 8, :path => ['subversion_test', 'helloworld.c'] assert_response :success assert_template 'annotate' assert_tag :tag => 'h2', :content => /@ 8/ From 3e1a39ef69ed8a2e7fd9163d2d8b347a94eef855 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 21 Feb 2011 03:59:50 +0000 Subject: [PATCH 072/440] Ruby 1.9 compatibility of unified_diff.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4897 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/unified_diff.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/redmine/unified_diff.rb b/lib/redmine/unified_diff.rb index 09fbfcf1..65d880dd 100644 --- a/lib/redmine/unified_diff.rb +++ b/lib/redmine/unified_diff.rb @@ -22,12 +22,20 @@ module Redmine options.assert_valid_keys(:type, :max_lines) diff = diff.split("\n") if diff.is_a?(String) diff_type = options[:type] || 'inline' - lines = 0 @truncated = false diff_table = DiffTable.new(diff_type) diff.each do |line| + line_encoding = nil + if line.respond_to?(:force_encoding) + line_encoding = line.encoding + # TODO: UTF-16 and Japanese CP932 which is imcompatible with ASCII + # In Japan, diffrence between file path encoding + # and file contents encoding is popular. + line.force_encoding('ASCII-8BIT') + end unless diff_table.add_line line + line.force_encoding(line_encoding) if line_encoding self << diff_table if diff_table.length > 1 diff_table = DiffTable.new(diff_type) end @@ -40,7 +48,7 @@ module Redmine self << diff_table unless diff_table.empty? self end - + def truncated?; @truncated; end end From d201aa7b48f6a7046c1812f7d7b048dc489111da Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 21 Feb 2011 04:00:12 +0000 Subject: [PATCH 073/440] scm: mercurial: add 'rhcat' function using URL encoding in mercurial helper extension (#2664). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4898 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial/redminehelper.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/redmine/scm/adapters/mercurial/redminehelper.py b/lib/redmine/scm/adapters/mercurial/redminehelper.py index a48560ce..9d498dfc 100644 --- a/lib/redmine/scm/adapters/mercurial/redminehelper.py +++ b/lib/redmine/scm/adapters/mercurial/redminehelper.py @@ -119,6 +119,9 @@ def _manifest(ui, repo, path, rev): ui.write('\n') +def rhcat(ui, repo, file1, *pats, **opts): + return commands.cat(ui, repo, urllib.unquote(file1), *map(urllib.unquote, pats), **opts) + def rhdiff(ui, repo, *pats, **opts): """diff repository (or selected files)""" change = opts.pop('change', None) @@ -156,6 +159,9 @@ def rhsummary(ui, repo, **opts): # This extension should be compatible with Mercurial 0.9.5. # Note that Mercurial 0.9.5 doesn't have extensions.wrapfunction(). cmdtable = { + 'rhcat': (rhcat, + [('r', 'rev', '', 'revision')], + 'hg rhcat ([-r REV] ...) FILE...'), 'rhdiff': (rhdiff, [('r', 'rev', [], 'revision'), ('c', 'change', '', 'change made by revision')], From 5ad7dfee4abb9be32425e400f3f678a26acc8152 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 21 Feb 2011 09:41:34 +0000 Subject: [PATCH 074/440] scm: add CP932 at Setting::ENCODINGS (#2664, #2274). CP932 is variant Japanese Shift_JIS on Windows. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4899 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/setting.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/setting.rb b/app/models/setting.rb index 70d8f2be..8f5b83b0 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -65,6 +65,7 @@ class Setting < ActiveRecord::Base UTF-16LE EUC-JP Shift_JIS + CP932 GB18030 GBK ISCII91 From bbb57ea4d27f2f97f4036ec99888c687274c64f5 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Mon, 21 Feb 2011 09:53:29 +0000 Subject: [PATCH 075/440] Warning on leaving a page with unsaved content in textarea (#2910). The warning can be turned off in the user's preference. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4900 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/application_helper.rb | 9 +++++ app/models/user_preference.rb | 3 ++ app/views/layouts/base.rhtml | 2 +- app/views/users/_preferences.html.erb | 1 + config/locales/en.yml | 2 + config/locales/fr.yml | 2 + public/javascripts/application.js | 43 ++++++++++++++++++++++ test/functional/welcome_controller_test.rb | 24 ++++++++++++ 8 files changed, 85 insertions(+), 1 deletion(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 67509b22..8a5c4d0d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -894,6 +894,15 @@ module ApplicationHelper '' end end + + # Returns the javascript tags that are included in the html layout head + def javascript_heads + tags = javascript_include_tag(:defaults) + unless User.current.pref.warn_on_leaving_unsaved == '0' + tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") + end + tags + end def favicon "" diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index 3daa7a74..85236ff6 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -51,4 +51,7 @@ class UserPreference < ActiveRecord::Base def comments_sorting; self[:comments_sorting] end def comments_sorting=(order); self[:comments_sorting]=order end + + def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end + def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end end diff --git a/app/views/layouts/base.rhtml b/app/views/layouts/base.rhtml index 18867fff..bae718b7 100644 --- a/app/views/layouts/base.rhtml +++ b/app/views/layouts/base.rhtml @@ -8,7 +8,7 @@ <%= favicon %> <%= stylesheet_link_tag 'application', :media => 'all' %> <%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %> -<%= javascript_include_tag :defaults %> +<%= javascript_heads %> <%= heads_for_theme %> <%= heads_for_wiki_formatter %> <%= yield :header_tags -%> - +
    From be4e4c80f754e8c70314bca0734d22f36b0472d2 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Mon, 28 Feb 2011 20:23:28 +0000 Subject: [PATCH 135/440] Stringify avatar to prevent "can't convert nil into String" errors on gantt (#7317). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4968 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/helpers/gantt.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/redmine/helpers/gantt.rb b/lib/redmine/helpers/gantt.rb index c0490e60..1279cb5e 100644 --- a/lib/redmine/helpers/gantt.rb +++ b/lib/redmine/helpers/gantt.rb @@ -357,7 +357,7 @@ module Redmine subject = "" if issue.assigned_to.present? assigned_string = l(:field_assigned_to) + ": " + issue.assigned_to.name - subject << view.avatar(issue.assigned_to, :class => 'gravatar icon-gravatar', :size => 10, :title => assigned_string) + subject << view.avatar(issue.assigned_to, :class => 'gravatar icon-gravatar', :size => 10, :title => assigned_string).to_s end subject << view.link_to_issue(issue) subject << '' From 8eaa4d10e5cb343fa03c960e2e1e333c058445a6 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 04:43:30 +0000 Subject: [PATCH 136/440] scm: add notes "local repository" in Git and Mercurial setting. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4974 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/repositories_helper.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 329e0daf..841ea3b9 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -190,11 +190,13 @@ module RepositoriesHelper end def mercurial_field_tags(form, repository) - content_tag('p', form.text_field(:url, :label => :label_mercurial_path, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?))) + content_tag('p', form.text_field(:url, :label => :label_mercurial_path, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) + + '
    local repository (e.g. /hgrepo, c:\hgrepo)' ) end def git_field_tags(form, repository) - content_tag('p', form.text_field(:url, :label => :label_git_path, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?))) + content_tag('p', form.text_field(:url, :label => :label_git_path, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) + + '
    a bare and local repository (e.g. /gitrepo, c:\gitrepo)') end def cvs_field_tags(form, repository) From 9c3c35e8b814a3c468d42238619215b92c665909 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 05:14:03 +0000 Subject: [PATCH 137/440] scm: add scm specific human_attribute_name for input validation. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4975 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/bazaar.rb | 7 +++++++ app/models/repository/cvs.rb | 8 ++++++++ app/models/repository/darcs.rb | 7 +++++++ app/models/repository/filesystem.rb | 7 +++++++ app/models/repository/git.rb | 7 +++++++ app/models/repository/mercurial.rb | 7 +++++++ 6 files changed, 43 insertions(+) diff --git a/app/models/repository/bazaar.rb b/app/models/repository/bazaar.rb index 9d7977e7..d68fabc9 100644 --- a/app/models/repository/bazaar.rb +++ b/app/models/repository/bazaar.rb @@ -21,6 +21,13 @@ class Repository::Bazaar < Repository attr_protected :root_url validates_presence_of :url + ATTRIBUTE_KEY_NAMES = { + "url" => "Root directory", + } + def self.human_attribute_name(attribute_key_name) + ATTRIBUTE_KEY_NAMES[attribute_key_name] || super + end + def self.scm_adapter_class Redmine::Scm::Adapters::BazaarAdapter end diff --git a/app/models/repository/cvs.rb b/app/models/repository/cvs.rb index 1c479d1b..e3dfced6 100644 --- a/app/models/repository/cvs.rb +++ b/app/models/repository/cvs.rb @@ -21,6 +21,14 @@ require 'digest/sha1' class Repository::Cvs < Repository validates_presence_of :url, :root_url + ATTRIBUTE_KEY_NAMES = { + "url" => "CVSROOT", + "root_url" => "Module", + } + def self.human_attribute_name(attribute_key_name) + ATTRIBUTE_KEY_NAMES[attribute_key_name] || super + end + def self.scm_adapter_class Redmine::Scm::Adapters::CvsAdapter end diff --git a/app/models/repository/darcs.rb b/app/models/repository/darcs.rb index dc3f0cee..c6d7cafd 100644 --- a/app/models/repository/darcs.rb +++ b/app/models/repository/darcs.rb @@ -20,6 +20,13 @@ require 'redmine/scm/adapters/darcs_adapter' class Repository::Darcs < Repository validates_presence_of :url + ATTRIBUTE_KEY_NAMES = { + "url" => "Root directory", + } + def self.human_attribute_name(attribute_key_name) + ATTRIBUTE_KEY_NAMES[attribute_key_name] || super + end + def self.scm_adapter_class Redmine::Scm::Adapters::DarcsAdapter end diff --git a/app/models/repository/filesystem.rb b/app/models/repository/filesystem.rb index 4be6b528..f06ad97c 100644 --- a/app/models/repository/filesystem.rb +++ b/app/models/repository/filesystem.rb @@ -24,6 +24,13 @@ class Repository::Filesystem < Repository attr_protected :root_url validates_presence_of :url + ATTRIBUTE_KEY_NAMES = { + "url" => "Root directory", + } + def self.human_attribute_name(attribute_key_name) + ATTRIBUTE_KEY_NAMES[attribute_key_name] || super + end + def self.scm_adapter_class Redmine::Scm::Adapters::FilesystemAdapter end diff --git a/app/models/repository/git.rb b/app/models/repository/git.rb index 63faea66..fb5c26a7 100644 --- a/app/models/repository/git.rb +++ b/app/models/repository/git.rb @@ -21,6 +21,13 @@ class Repository::Git < Repository attr_protected :root_url validates_presence_of :url + ATTRIBUTE_KEY_NAMES = { + "url" => "Path to repository", + } + def self.human_attribute_name(attribute_key_name) + ATTRIBUTE_KEY_NAMES[attribute_key_name] || super + end + def self.scm_adapter_class Redmine::Scm::Adapters::GitAdapter end diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index 98575a56..021e60b0 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -26,6 +26,13 @@ class Repository::Mercurial < Repository FETCH_AT_ONCE = 100 # number of changesets to fetch at once + ATTRIBUTE_KEY_NAMES = { + "url" => "Root directory", + } + def self.human_attribute_name(attribute_key_name) + ATTRIBUTE_KEY_NAMES[attribute_key_name] || super + end + def self.scm_adapter_class Redmine::Scm::Adapters::MercurialAdapter end From 57298dcc82b4de078a84933e4aa75b32cba1d47f Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 05:49:14 +0000 Subject: [PATCH 138/440] scm: code clean up at test/unit/changeset_test.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4976 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/changeset_test.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/changeset_test.rb b/test/unit/changeset_test.rb index d1dbb44e..3884096b 100644 --- a/test/unit/changeset_test.rb +++ b/test/unit/changeset_test.rb @@ -259,7 +259,6 @@ class ChangesetTest < ActiveSupport::TestCase def test_comments_should_be_converted_all_latin1_to_utf8 with_settings :commit_logs_encoding => 'ISO-8859-1' do - c = Changeset.new s1 = "\xC2\x80" s2 = "\xc3\x82\xc2\x80" if s1.respond_to?(:force_encoding) From 57455eff5fa07d0e359f20744603ddc76d0727ce Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 07:03:21 +0000 Subject: [PATCH 139/440] scm: bazaar: change project id of unit app test from 1 to 3. Project id 1 has Subversion fixtures. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4977 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_bazaar_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/repository_bazaar_test.rb b/test/unit/repository_bazaar_test.rb index 55d3b8a2..38f2af49 100644 --- a/test/unit/repository_bazaar_test.rb +++ b/test/unit/repository_bazaar_test.rb @@ -25,7 +25,7 @@ class RepositoryBazaarTest < ActiveSupport::TestCase REPOSITORY_PATH.gsub!(/\/+/, '/') def setup - @project = Project.find(1) + @project = Project.find(3) assert @repository = Repository::Bazaar.create(:project => @project, :url => "file:///#{REPOSITORY_PATH}") end From e5619d536837bae4c9abce28993439df90ab45f9 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 07:12:56 +0000 Subject: [PATCH 140/440] scm: darcs: change project id of unit app test from 1 to 3. Project id 1 has Subversion fixtures. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4978 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_darcs_test.rb | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/test/unit/repository_darcs_test.rb b/test/unit/repository_darcs_test.rb index d470bebf..ef833e93 100644 --- a/test/unit/repository_darcs_test.rb +++ b/test/unit/repository_darcs_test.rb @@ -19,25 +19,26 @@ require File.expand_path('../../test_helper', __FILE__) class RepositoryDarcsTest < ActiveSupport::TestCase fixtures :projects - + # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/darcs_repository' - + def setup - @project = Project.find(1) - assert @repository = Repository::Darcs.create(:project => @project, :url => REPOSITORY_PATH) + @project = Project.find(3) + @repository = Repository::Darcs.create(:project => @project, :url => REPOSITORY_PATH) + assert @repository end - + if File.directory?(REPOSITORY_PATH) def test_fetch_changesets_from_scratch @repository.fetch_changesets @repository.reload - + assert_equal 6, @repository.changesets.count assert_equal 13, @repository.changes.count assert_equal "Initial commit.", @repository.changesets.find_by_revision('1').comments end - + def test_fetch_changesets_incremental @repository.fetch_changesets # Remove changesets with revision > 3 @@ -48,8 +49,10 @@ class RepositoryDarcsTest < ActiveSupport::TestCase @repository.fetch_changesets assert_equal 6, @repository.changesets.count end - + def test_deleted_files_should_not_be_listed + @repository.fetch_changesets + @repository.reload entries = @repository.entries('sources') assert entries.detect {|e| e.name == 'watchers_controller.rb'} assert_nil entries.detect {|e| e.name == 'welcome_controller.rb'} From aae9747e65cd75f78572c74fd2878ec8139ed5e6 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 07:38:05 +0000 Subject: [PATCH 141/440] scm: darcs: refactor functional test. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4979 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../repositories_darcs_controller_test.rb | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/test/functional/repositories_darcs_controller_test.rb b/test/functional/repositories_darcs_controller_test.rb index 0a5d57a8..a315f9fa 100644 --- a/test/functional/repositories_darcs_controller_test.rb +++ b/test/functional/repositories_darcs_controller_test.rb @@ -26,26 +26,33 @@ class RepositoriesDarcsControllerTest < ActionController::TestCase # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/darcs_repository' + PRJ_ID = 3 def setup @controller = RepositoriesController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new User.current = nil - Repository::Darcs.create(:project => Project.find(3), :url => REPOSITORY_PATH) + @project = Project.find(PRJ_ID) + @repository = Repository::Darcs.create(:project => @project, :url => REPOSITORY_PATH) + assert @repository end - + if File.directory?(REPOSITORY_PATH) def test_show - get :show, :id => 3 + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID assert_response :success assert_template 'show' assert_not_nil assigns(:entries) assert_not_nil assigns(:changesets) end - + def test_browse_root - get :show, :id => 3 + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID assert_response :success assert_template 'show' assert_not_nil assigns(:entries) @@ -54,9 +61,11 @@ class RepositoriesDarcsControllerTest < ActionController::TestCase assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'} assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'} end - + def test_browse_directory - get :show, :id => 3, :path => ['images'] + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID, :path => ['images'] assert_response :success assert_template 'show' assert_not_nil assigns(:entries) @@ -66,27 +75,31 @@ class RepositoriesDarcsControllerTest < ActionController::TestCase assert_equal 'file', entry.kind assert_equal 'images/edit.png', entry.path end - + def test_browse_at_given_revision - Project.find(3).repository.fetch_changesets - get :show, :id => 3, :path => ['images'], :rev => 1 + @repository.fetch_changesets + @repository.reload + get :show, :id => PRJ_ID, :path => ['images'], :rev => 1 assert_response :success assert_template 'show' assert_not_nil assigns(:entries) assert_equal ['delete.png'], assigns(:entries).collect(&:name) end - + def test_changes - get :changes, :id => 3, :path => ['images', 'edit.png'] + @repository.fetch_changesets + @repository.reload + get :changes, :id => PRJ_ID, :path => ['images', 'edit.png'] assert_response :success assert_template 'changes' assert_tag :tag => 'h2', :content => 'edit.png' end - + def test_diff - Project.find(3).repository.fetch_changesets + @repository.fetch_changesets + @repository.reload # Full diff of changeset 5 - get :diff, :id => 3, :rev => 5 + get :diff, :id => PRJ_ID, :rev => 5 assert_response :success assert_template 'diff' # Line 22 removed From ab8bdf282b01cc99c7ab18b0b24427e77d6d8a7c Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 09:47:06 +0000 Subject: [PATCH 142/440] scm: add log_encoding column to repositories table (#1735). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4980 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../20110228000000_add_repositories_log_encoding.rb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 db/migrate/20110228000000_add_repositories_log_encoding.rb diff --git a/db/migrate/20110228000000_add_repositories_log_encoding.rb b/db/migrate/20110228000000_add_repositories_log_encoding.rb new file mode 100644 index 00000000..85cadafc --- /dev/null +++ b/db/migrate/20110228000000_add_repositories_log_encoding.rb @@ -0,0 +1,9 @@ +class AddRepositoriesLogEncoding < ActiveRecord::Migration + def self.up + add_column :repositories, :log_encoding, :string, :limit => 64, :default => nil + end + + def self.down + remove_column :repositories, :log_encoding + end +end From 231fcf6fd8f0269a737d652b6ffe00df7ca2a462 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 10:14:47 +0000 Subject: [PATCH 143/440] scm: copy global log encoding setting to repository (#1735). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4981 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- ...228000100_copy_repositories_log_encoding.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 db/migrate/20110228000100_copy_repositories_log_encoding.rb diff --git a/db/migrate/20110228000100_copy_repositories_log_encoding.rb b/db/migrate/20110228000100_copy_repositories_log_encoding.rb new file mode 100644 index 00000000..4d975f80 --- /dev/null +++ b/db/migrate/20110228000100_copy_repositories_log_encoding.rb @@ -0,0 +1,18 @@ +class CopyRepositoriesLogEncoding < ActiveRecord::Migration + def self.up + encoding = Setting.commit_logs_encoding.to_s.strip + encoding = encoding.blank? ? 'UTF-8' : encoding + Repository.find(:all).each do |repo| + scm = repo.scm_name + case scm + when 'Subversion', 'Mercurial', 'Git', 'Filesystem' + repo.update_attribute(:log_encoding, nil) + else + repo.update_attribute(:log_encoding, encoding) + end + end + end + + def self.down + end +end From e383414c31284e816f5230414c125cb42056febe Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 10:27:30 +0000 Subject: [PATCH 144/440] scm: add feature of per project repository log encoding setting (#1735). Subversion, Mercurial and Git supports UTF-8 log. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4982 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/repositories_helper.rb | 12 ++++++++--- app/models/repository.rb | 2 +- app/models/repository/bazaar.rb | 3 ++- app/models/repository/cvs.rb | 3 ++- app/models/repository/darcs.rb | 3 ++- .../repositories_bazaar_controller_test.rb | 12 +++++++---- .../repositories_cvs_controller_test.rb | 3 ++- .../repositories_darcs_controller_test.rb | 4 +++- test/unit/changeset_test.rb | 21 ++++++++++--------- test/unit/helpers/application_helper_test.rb | 4 +++- test/unit/repository_bazaar_test.rb | 7 +++++-- test/unit/repository_cvs_test.rb | 8 ++++--- test/unit/repository_darcs_test.rb | 4 +++- test/unit/repository_test.rb | 11 ++++++---- 14 files changed, 63 insertions(+), 34 deletions(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 841ea3b9..4bea43d2 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -186,7 +186,9 @@ module RepositoriesHelper end def darcs_field_tags(form, repository) - content_tag('p', form.text_field(:url, :label => :label_darcs_path, :size => 60, :required => true, :disabled => (repository && !repository.new_record?))) + content_tag('p', form.text_field(:url, :label => :label_darcs_path, :size => 60, :required => true, :disabled => (repository && !repository.new_record?))) + + content_tag('p', form.select(:log_encoding, [nil] + Setting::ENCODINGS, + :label => 'Commit messages encoding', :required => true)) end def mercurial_field_tags(form, repository) @@ -201,11 +203,15 @@ module RepositoriesHelper def cvs_field_tags(form, repository) content_tag('p', form.text_field(:root_url, :label => :label_cvs_path, :size => 60, :required => true, :disabled => !repository.new_record?)) + - content_tag('p', form.text_field(:url, :label => :label_cvs_module, :size => 30, :required => true, :disabled => !repository.new_record?)) + content_tag('p', form.text_field(:url, :label => :label_cvs_module, :size => 30, :required => true, :disabled => !repository.new_record?)) + + content_tag('p', form.select(:log_encoding, [nil] + Setting::ENCODINGS, + :label => 'Commit messages encoding', :required => true)) end def bazaar_field_tags(form, repository) - content_tag('p', form.text_field(:url, :label => :label_bazaar_path, :size => 60, :required => true, :disabled => (repository && !repository.new_record?))) + content_tag('p', form.text_field(:url, :label => :label_bazaar_path, :size => 60, :required => true, :disabled => (repository && !repository.new_record?))) + + content_tag('p', form.select(:log_encoding, [nil] + Setting::ENCODINGS, + :label => 'Commit messages encoding', :required => true)) end def filesystem_field_tags(form, repository) diff --git a/app/models/repository.rb b/app/models/repository.rb index bddbbbec..07e24af2 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -191,7 +191,7 @@ class Repository < ActiveRecord::Base end def repo_log_encoding - encoding = Setting.commit_logs_encoding.to_s.strip + encoding = log_encoding.to_s.strip encoding.blank? ? 'UTF-8' : encoding end diff --git a/app/models/repository/bazaar.rb b/app/models/repository/bazaar.rb index d68fabc9..3ae8b28f 100644 --- a/app/models/repository/bazaar.rb +++ b/app/models/repository/bazaar.rb @@ -19,10 +19,11 @@ require 'redmine/scm/adapters/bazaar_adapter' class Repository::Bazaar < Repository attr_protected :root_url - validates_presence_of :url + validates_presence_of :url, :log_encoding ATTRIBUTE_KEY_NAMES = { "url" => "Root directory", + "log_encoding" => "Commit messages encoding", } def self.human_attribute_name(attribute_key_name) ATTRIBUTE_KEY_NAMES[attribute_key_name] || super diff --git a/app/models/repository/cvs.rb b/app/models/repository/cvs.rb index e3dfced6..2ee82a74 100644 --- a/app/models/repository/cvs.rb +++ b/app/models/repository/cvs.rb @@ -19,11 +19,12 @@ require 'redmine/scm/adapters/cvs_adapter' require 'digest/sha1' class Repository::Cvs < Repository - validates_presence_of :url, :root_url + validates_presence_of :url, :root_url, :log_encoding ATTRIBUTE_KEY_NAMES = { "url" => "CVSROOT", "root_url" => "Module", + "log_encoding" => "Commit messages encoding", } def self.human_attribute_name(attribute_key_name) ATTRIBUTE_KEY_NAMES[attribute_key_name] || super diff --git a/app/models/repository/darcs.rb b/app/models/repository/darcs.rb index c6d7cafd..c8870e29 100644 --- a/app/models/repository/darcs.rb +++ b/app/models/repository/darcs.rb @@ -18,10 +18,11 @@ require 'redmine/scm/adapters/darcs_adapter' class Repository::Darcs < Repository - validates_presence_of :url + validates_presence_of :url, :log_encoding ATTRIBUTE_KEY_NAMES = { "url" => "Root directory", + "log_encoding" => "Commit messages encoding", } def self.human_attribute_name(attribute_key_name) ATTRIBUTE_KEY_NAMES[attribute_key_name] || super diff --git a/test/functional/repositories_bazaar_controller_test.rb b/test/functional/repositories_bazaar_controller_test.rb index 5f7de1de..576b710c 100644 --- a/test/functional/repositories_bazaar_controller_test.rb +++ b/test/functional/repositories_bazaar_controller_test.rb @@ -32,9 +32,13 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new User.current = nil - Repository::Bazaar.create(:project => Project.find(3), :url => REPOSITORY_PATH) + @project = Project.find(3) + @repository = Repository::Bazaar.create( + :project => @project, :url => REPOSITORY_PATH, + :log_encoding => 'UTF-8') + assert @repository end - + if File.directory?(REPOSITORY_PATH) def test_show get :show, :id => 3 @@ -43,7 +47,7 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase assert_not_nil assigns(:entries) assert_not_nil assigns(:changesets) end - + def test_browse_root get :show, :id => 3 assert_response :success @@ -53,7 +57,7 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase assert assigns(:entries).detect {|e| e.name == 'directory' && e.kind == 'dir'} assert assigns(:entries).detect {|e| e.name == 'doc-mkdir.txt' && e.kind == 'file'} end - + def test_browse_directory get :show, :id => 3, :path => ['directory'] assert_response :success diff --git a/test/functional/repositories_cvs_controller_test.rb b/test/functional/repositories_cvs_controller_test.rb index ca040e3f..6a6be388 100644 --- a/test/functional/repositories_cvs_controller_test.rb +++ b/test/functional/repositories_cvs_controller_test.rb @@ -41,7 +41,8 @@ class RepositoriesCvsControllerTest < ActionController::TestCase @project = Project.find(PRJ_ID) @repository = Repository::Cvs.create(:project => Project.find(PRJ_ID), :root_url => REPOSITORY_PATH, - :url => MODULE_NAME) + :url => MODULE_NAME, + :log_encoding => 'UTF-8') assert @repository end diff --git a/test/functional/repositories_darcs_controller_test.rb b/test/functional/repositories_darcs_controller_test.rb index a315f9fa..d78149ca 100644 --- a/test/functional/repositories_darcs_controller_test.rb +++ b/test/functional/repositories_darcs_controller_test.rb @@ -34,7 +34,9 @@ class RepositoriesDarcsControllerTest < ActionController::TestCase @response = ActionController::TestResponse.new User.current = nil @project = Project.find(PRJ_ID) - @repository = Repository::Darcs.create(:project => @project, :url => REPOSITORY_PATH) + @repository = Repository::Darcs.create( + :project => @project, :url => REPOSITORY_PATH, + :log_encoding => 'UTF-8') assert @repository end diff --git a/test/unit/changeset_test.rb b/test/unit/changeset_test.rb index 3884096b..767192db 100644 --- a/test/unit/changeset_test.rb +++ b/test/unit/changeset_test.rb @@ -220,12 +220,13 @@ class ChangesetTest < ActiveSupport::TestCase changeset = Changeset.find_by_revision('10') assert_nil changeset.next end - + def test_comments_should_be_converted_to_utf8 - with_settings :commit_logs_encoding => 'ISO-8859-1' do proj = Project.find(3) str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") - r = Repository::Bazaar.create!(:project => proj, :url => '/tmp/test/bazaar') + r = Repository::Bazaar.create!( + :project => proj, :url => '/tmp/test/bazaar', + :log_encoding => 'ISO-8859-1' ) assert r c = Changeset.new(:repository => r, :committed_on => Time.now, @@ -234,14 +235,14 @@ class ChangesetTest < ActiveSupport::TestCase :comments => str) assert( c.save ) assert_equal "Texte encodé en ISO-8859-1.", c.comments - end end def test_invalid_utf8_sequences_in_comments_should_be_stripped - with_settings :commit_logs_encoding => 'UTF-8' do proj = Project.find(3) str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") - r = Repository::Bazaar.create!(:project => proj, :url => '/tmp/test/bazaar') + r = Repository::Bazaar.create!( + :project => proj, :url => '/tmp/test/bazaar', + :log_encoding => 'UTF-8' ) assert r c = Changeset.new(:repository => r, :committed_on => Time.now, @@ -254,11 +255,9 @@ class ChangesetTest < ActiveSupport::TestCase else assert_equal "Texte encod en ISO-8859-1.", c.comments end - end end def test_comments_should_be_converted_all_latin1_to_utf8 - with_settings :commit_logs_encoding => 'ISO-8859-1' do s1 = "\xC2\x80" s2 = "\xc3\x82\xc2\x80" if s1.respond_to?(:force_encoding) @@ -271,7 +270,10 @@ class ChangesetTest < ActiveSupport::TestCase assert_equal s3.encode('UTF-8'), s4 end proj = Project.find(3) - r = Repository::Bazaar.create!(:project => proj, :url => '/tmp/test/bazaar') + r = Repository::Bazaar.create!( + :project => proj, :url => '/tmp/test/bazaar', + :log_encoding => 'ISO-8859-1' ) + assert r assert r c = Changeset.new(:repository => r, :committed_on => Time.now, @@ -280,7 +282,6 @@ class ChangesetTest < ActiveSupport::TestCase :comments => s1) assert( c.save ) assert_equal s2, c.comments - end end def test_identifier diff --git a/test/unit/helpers/application_helper_test.rb b/test/unit/helpers/application_helper_test.rb index 69eaf745..aa2c6277 100644 --- a/test/unit/helpers/application_helper_test.rb +++ b/test/unit/helpers/application_helper_test.rb @@ -292,7 +292,9 @@ RAW 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link, } @project = Project.find(3) - r = Repository::Darcs.create!(:project => @project, :url => '/tmp/test/darcs') + r = Repository::Darcs.create!( + :project => @project, :url => '/tmp/test/darcs', + :log_encoding => 'UTF-8') assert r c = Changeset.new(:repository => r, :committed_on => Time.now, diff --git a/test/unit/repository_bazaar_test.rb b/test/unit/repository_bazaar_test.rb index 38f2af49..b2515fe3 100644 --- a/test/unit/repository_bazaar_test.rb +++ b/test/unit/repository_bazaar_test.rb @@ -19,14 +19,17 @@ require File.expand_path('../../test_helper', __FILE__) class RepositoryBazaarTest < ActiveSupport::TestCase fixtures :projects - + # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/bazaar_repository' REPOSITORY_PATH.gsub!(/\/+/, '/') def setup @project = Project.find(3) - assert @repository = Repository::Bazaar.create(:project => @project, :url => "file:///#{REPOSITORY_PATH}") + @repository = Repository::Bazaar.create( + :project => @project, :url => "file:///#{REPOSITORY_PATH}", + :log_encoding => 'UTF-8') + assert @repository end if File.directory?(REPOSITORY_PATH) diff --git a/test/unit/repository_cvs_test.rb b/test/unit/repository_cvs_test.rb index a5da09f5..0fd81615 100644 --- a/test/unit/repository_cvs_test.rb +++ b/test/unit/repository_cvs_test.rb @@ -28,9 +28,11 @@ class RepositoryCvsTest < ActiveSupport::TestCase def setup @project = Project.find(3) - assert @repository = Repository::Cvs.create(:project => @project, - :root_url => REPOSITORY_PATH, - :url => MODULE_NAME) + @repository = Repository::Cvs.create(:project => @project, + :root_url => REPOSITORY_PATH, + :url => MODULE_NAME, + :log_encoding => 'UTF-8') + assert @repository end if File.directory?(REPOSITORY_PATH) diff --git a/test/unit/repository_darcs_test.rb b/test/unit/repository_darcs_test.rb index ef833e93..2e16973c 100644 --- a/test/unit/repository_darcs_test.rb +++ b/test/unit/repository_darcs_test.rb @@ -25,7 +25,9 @@ class RepositoryDarcsTest < ActiveSupport::TestCase def setup @project = Project.find(3) - @repository = Repository::Darcs.create(:project => @project, :url => REPOSITORY_PATH) + @repository = Repository::Darcs.create( + :project => @project, :url => REPOSITORY_PATH, + :log_encoding => 'UTF-8') assert @repository end diff --git a/test/unit/repository_test.rb b/test/unit/repository_test.rb index 252230b2..9bf22df2 100644 --- a/test/unit/repository_test.rb +++ b/test/unit/repository_test.rb @@ -126,16 +126,19 @@ class RepositoryTest < ActiveSupport::TestCase assert_not_equal( comment, changeset.comments ) assert_equal( 'This is a loooooooooooooooooooooooooooong comment', changeset.comments ) end - + def test_for_urls_strip - repository = Repository::Cvs.create(:project => Project.find(4), :url => ' :pserver:login:password@host:/path/to/the/repository', - :root_url => 'foo ') + repository = Repository::Cvs.create( + :project => Project.find(4), + :url => ' :pserver:login:password@host:/path/to/the/repository', + :root_url => 'foo ', + :log_encoding => 'UTF-8') assert repository.save repository.reload assert_equal ':pserver:login:password@host:/path/to/the/repository', repository.url assert_equal 'foo', repository.root_url end - + def test_manual_user_mapping assert_no_difference "Changeset.count(:conditions => 'user_id <> 2')" do c = Changeset.create!(:repository => @repository, :committer => 'foo', :committed_on => Time.now, :revision => 100, :comments => 'Committed by foo.') From 1c5e441b65bff3f92347cd53defbffab1443351d Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 10:27:51 +0000 Subject: [PATCH 145/440] scm: remove global repository log encoding setting from view (#1735). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4983 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/settings/_repositories.rhtml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/views/settings/_repositories.rhtml b/app/views/settings/_repositories.rhtml index 9f2b26d4..7f892c2d 100644 --- a/app/views/settings/_repositories.rhtml +++ b/app/views/settings/_repositories.rhtml @@ -18,8 +18,6 @@

    <%= setting_text_field :repositories_encodings, :size => 60 %>
    <%= l(:text_comma_separated) %>

    -

    <%= setting_select :commit_logs_encoding, Setting::ENCODINGS %>

    -

    <%= setting_text_field :repository_log_display_limit, :size => 6 %>

    From a9a6abe40a98f3ddbcf44fe4882f89dd02cb65e2 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Tue, 1 Mar 2011 15:35:27 +0000 Subject: [PATCH 146/440] scm: code clean up test/unit/changeset_test.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4984 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/changeset_test.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/unit/changeset_test.rb b/test/unit/changeset_test.rb index 767192db..4da43d1c 100644 --- a/test/unit/changeset_test.rb +++ b/test/unit/changeset_test.rb @@ -185,12 +185,12 @@ class ChangesetTest < ActiveSupport::TestCase assert_equal [2], c.issue_ids.sort assert c.issues.first.project != c.project end - + def test_text_tag_revision c = Changeset.new(:revision => '520') assert_equal 'r520', c.text_tag end - + def test_text_tag_hash c = Changeset.new(:scmid => '7234cb2750b63f47bff735edc50a1c0a433c2518', :revision => '7234cb2750b63f47bff735edc50a1c0a433c2518') assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag @@ -236,7 +236,7 @@ class ChangesetTest < ActiveSupport::TestCase assert( c.save ) assert_equal "Texte encodé en ISO-8859-1.", c.comments end - + def test_invalid_utf8_sequences_in_comments_should_be_stripped proj = Project.find(3) str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") @@ -274,7 +274,6 @@ class ChangesetTest < ActiveSupport::TestCase :project => proj, :url => '/tmp/test/bazaar', :log_encoding => 'ISO-8859-1' ) assert r - assert r c = Changeset.new(:repository => r, :committed_on => Time.now, :revision => '123', From b91649ab41358f2810b47ee66e90f7266654eb8f Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 2 Mar 2011 05:12:15 +0000 Subject: [PATCH 147/440] scm: code clean up repositories_helper.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4985 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/repositories_helper.rb | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 4bea43d2..b820eadd 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -151,19 +151,31 @@ module RepositoriesHelper def repository_field_tags(form, repository) method = repository.class.name.demodulize.underscore + "_field_tags" - send(method, form, repository) if repository.is_a?(Repository) && respond_to?(method) && method != 'repository_field_tags' + if repository.is_a?(Repository) && + respond_to?(method) && method != 'repository_field_tags' + send(method, form, repository) + end end - + def scm_select_tag(repository) scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']] Redmine::Scm::Base.all.each do |scm| - scm_options << ["Repository::#{scm}".constantize.scm_name, scm] if Setting.enabled_scm.include?(scm) || (repository && repository.class.name.demodulize == scm) + if Setting.enabled_scm.include?(scm) || + (repository && repository.class.name.demodulize == scm) + scm_options << ["Repository::#{scm}".constantize.scm_name, scm] + end end - select_tag('repository_scm', options_for_select(scm_options, repository.class.name.demodulize), :disabled => (repository && !repository.new_record?), - :onchange => remote_function(:url => { :controller => 'repositories', :action => 'edit', :id => @project }, :method => :get, :with => "Form.serialize(this.form)") + :onchange => remote_function( + :url => { + :controller => 'repositories', + :action => 'edit', + :id => @project + }, + :method => :get, + :with => "Form.serialize(this.form)") ) end From c54cd8a088118cce7f4013ad4d3706b69d1be465 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 2 Mar 2011 05:12:39 +0000 Subject: [PATCH 148/440] scm: git: add more tests in fetch changesets incremental unit model test (#5357). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4986 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_git_test.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/unit/repository_git_test.rb b/test/unit/repository_git_test.rb index baa17641..c6e2d837 100644 --- a/test/unit/repository_git_test.rb +++ b/test/unit/repository_git_test.rb @@ -61,8 +61,18 @@ class RepositoryGitTest < ActiveSupport::TestCase # Remove the 3 latest changesets @repository.changesets.find(:all, :order => 'committed_on DESC', :limit => 3).each(&:destroy) @repository.reload - assert_equal 13, @repository.changesets.count - + cs1 = @repository.changesets + assert_equal 13, cs1.count + + rev_a_commit = @repository.changesets.find(:first, :order => 'committed_on DESC') + assert_equal '4f26664364207fa8b1af9f8722647ab2d4ac5d43', rev_a_commit.revision + # Mon Jul 5 22:34:26 2010 +0200 + rev_a_committed_on = Time.gm(2010, 7, 5, 20, 34, 26) + assert_equal '4f26664364207fa8b1af9f8722647ab2d4ac5d43', rev_a_commit.scmid + assert_equal rev_a_committed_on, rev_a_commit.committed_on + latest_rev = @repository.latest_changeset + assert_equal rev_a_committed_on, latest_rev.committed_on + @repository.fetch_changesets assert_equal 16, @repository.changesets.count end From fb4601221aac6fae724115f29efd0c8e73fcea53 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 2 Mar 2011 07:10:39 +0000 Subject: [PATCH 149/440] scm: subversion: add changesets order test in unit model test (#5357). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4987 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_subversion_test.rb | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/unit/repository_subversion_test.rb b/test/unit/repository_subversion_test.rb index 158f17c5..c111956a 100644 --- a/test/unit/repository_subversion_test.rb +++ b/test/unit/repository_subversion_test.rb @@ -159,6 +159,34 @@ class RepositorySubversionTest < ActiveSupport::TestCase assert_equal s2, c.comments end end + + def test_previous + @repository.fetch_changesets + @repository.reload + changeset = @repository.find_changeset_by_name('3') + assert_equal @repository.find_changeset_by_name('2'), changeset.previous + end + + def test_previous_nil + @repository.fetch_changesets + @repository.reload + changeset = @repository.find_changeset_by_name('1') + assert_nil changeset.previous + end + + def test_next + @repository.fetch_changesets + @repository.reload + changeset = @repository.find_changeset_by_name('2') + assert_equal @repository.find_changeset_by_name('3'), changeset.next + end + + def test_next_nil + @repository.fetch_changesets + @repository.reload + changeset = @repository.find_changeset_by_name('11') + assert_nil changeset.next + end else puts "Subversion test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end From ce16f4a27873fa1c8d12bbe009ad2540fd3fac65 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 2 Mar 2011 07:11:00 +0000 Subject: [PATCH 150/440] scm: filesystem: add note "Default: UTF-8" in path encoding setting (#2274). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4988 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/repositories_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index b820eadd..23899a88 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -229,7 +229,8 @@ module RepositoriesHelper def filesystem_field_tags(form, repository) content_tag('p', form.text_field(:url, :label => :label_filesystem_path, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?))) + content_tag('p', form.select(:path_encoding, [nil] + Setting::ENCODINGS, - :label => 'Path encoding')) + :label => 'Path encoding') + + '
    Default: UTF-8') end end From b00caa6e48c20102690d7efc76ab75a338f910e0 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 2 Mar 2011 10:17:36 +0000 Subject: [PATCH 151/440] scm: mercurial: wrap revison, tag and branch with URL encoding for entries (#4455, #1981, #7246). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4989 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial/redminehelper.py | 2 +- lib/redmine/scm/adapters/mercurial_adapter.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial/redminehelper.py b/lib/redmine/scm/adapters/mercurial/redminehelper.py index 9bca6c9b..e6c9182f 100644 --- a/lib/redmine/scm/adapters/mercurial/redminehelper.py +++ b/lib/redmine/scm/adapters/mercurial/redminehelper.py @@ -140,7 +140,7 @@ def rhmanifest(ui, repo, path='', **opts): ui.write('\n') ui.write('\n' % _u(repo.root)) try: - _manifest(ui, repo, urllib.unquote_plus(path), opts.get('rev')) + _manifest(ui, repo, urllib.unquote_plus(path), urllib.unquote_plus(opts.get('rev'))) finally: ui.write('\n') ui.write('\n') diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 11eb66b6..c60eb99e 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -130,7 +130,7 @@ module Redmine def entries(path=nil, identifier=nil) p1 = scm_iconv(@path_encoding, 'UTF-8', path) - manifest = hg('rhmanifest', '-r', hgrev(identifier), + manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)), CGI.escape(without_leading_slash(p1.to_s))) do |io| begin ActiveSupport::XmlMini.parse(io.read)['rhmanifest']['repository']['manifest'] From 15abee2ee5dbcf5829bda9e5751cfa940ca5a8d7 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Thu, 3 Mar 2011 03:35:13 +0000 Subject: [PATCH 152/440] scm: mercurial: code clean up unit model test. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4991 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_mercurial_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index 5b2c70e6..271ffe43 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -28,7 +28,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase @repository = Repository::Mercurial.create(:project => @project, :url => REPOSITORY_PATH) assert @repository end - + if File.directory?(REPOSITORY_PATH) def test_fetch_changesets_from_scratch @repository.fetch_changesets @@ -38,7 +38,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase assert_equal "Initial import.\nThe repository contains 3 files.", @repository.changesets.find_by_revision('0').comments end - + def test_fetch_changesets_incremental @repository.fetch_changesets # Remove changesets with revision > 2 @@ -49,7 +49,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase @repository.fetch_changesets assert_equal 17, @repository.changesets.count end - + def test_isodatesec # Template keyword 'isodatesec' supported in Mercurial 1.0 and higher if @repository.scm.class.client_version_above?([1, 0]) From ce01f49ca7ba9e854aa1469a65bf29edd14dfb25 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Thu, 3 Mar 2011 05:32:33 +0000 Subject: [PATCH 153/440] scm: fix unit tests fails in Ruby 1.9. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4992 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/bazaar_adapter.rb | 2 +- lib/redmine/scm/adapters/cvs_adapter.rb | 2 +- lib/redmine/scm/adapters/darcs_adapter.rb | 2 +- lib/redmine/scm/adapters/git_adapter.rb | 2 +- lib/redmine/scm/adapters/mercurial_adapter.rb | 2 +- lib/redmine/scm/adapters/subversion_adapter.rb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/redmine/scm/adapters/bazaar_adapter.rb b/lib/redmine/scm/adapters/bazaar_adapter.rb index 92a1d693..b39150de 100644 --- a/lib/redmine/scm/adapters/bazaar_adapter.rb +++ b/lib/redmine/scm/adapters/bazaar_adapter.rb @@ -43,7 +43,7 @@ module Redmine end def scm_command_version - scm_version = scm_version_from_command_line + scm_version = scm_version_from_command_line.dup if scm_version.respond_to?(:force_encoding) scm_version.force_encoding('ASCII-8BIT') end diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb index 762e5c68..a557199a 100644 --- a/lib/redmine/scm/adapters/cvs_adapter.rb +++ b/lib/redmine/scm/adapters/cvs_adapter.rb @@ -43,7 +43,7 @@ module Redmine end def scm_command_version - scm_version = scm_version_from_command_line + scm_version = scm_version_from_command_line.dup if scm_version.respond_to?(:force_encoding) scm_version.force_encoding('ASCII-8BIT') end diff --git a/lib/redmine/scm/adapters/darcs_adapter.rb b/lib/redmine/scm/adapters/darcs_adapter.rb index 9b79e653..92864388 100644 --- a/lib/redmine/scm/adapters/darcs_adapter.rb +++ b/lib/redmine/scm/adapters/darcs_adapter.rb @@ -43,7 +43,7 @@ module Redmine end def darcs_binary_version - darcsversion = darcs_binary_version_from_command_line + darcsversion = darcs_binary_version_from_command_line.dup if darcsversion.respond_to?(:force_encoding) darcsversion.force_encoding('ASCII-8BIT') end diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index 6ad7426c..6d2c34ac 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -48,7 +48,7 @@ module Redmine end def scm_command_version - scm_version = scm_version_from_command_line + scm_version = scm_version_from_command_line.dup if scm_version.respond_to?(:force_encoding) scm_version.force_encoding('ASCII-8BIT') end diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index c60eb99e..a0f1db19 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -54,7 +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 + theversion = hgversion_from_command_line.dup if theversion.respond_to?(:force_encoding) theversion.force_encoding('ASCII-8BIT') end diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb index 9f1ccf7a..1fad6e3f 100644 --- a/lib/redmine/scm/adapters/subversion_adapter.rb +++ b/lib/redmine/scm/adapters/subversion_adapter.rb @@ -44,7 +44,7 @@ module Redmine end def svn_binary_version - scm_version = scm_version_from_command_line + scm_version = scm_version_from_command_line.dup if scm_version.respond_to?(:force_encoding) scm_version.force_encoding('ASCII-8BIT') end From ac227939ade8c6067f8de24182406f31ae14a787 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Thu, 3 Mar 2011 05:51:46 +0000 Subject: [PATCH 154/440] scm: Ruby 1.9 compatibility for XML UTF-8 parsing. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4993 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 18 +++++++++++++++--- lib/redmine/scm/adapters/subversion_adapter.rb | 12 ++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index a0f1db19..1f9153fa 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -120,8 +120,12 @@ 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 begin - @summary = ActiveSupport::XmlMini.parse(io.read)['rhsummary'] + @summary = ActiveSupport::XmlMini.parse(output)['rhsummary'] rescue end end @@ -132,8 +136,12 @@ 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 begin - ActiveSupport::XmlMini.parse(io.read)['rhmanifest']['repository']['manifest'] + ActiveSupport::XmlMini.parse(output)['rhmanifest']['repository']['manifest'] rescue end end @@ -175,9 +183,13 @@ 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 begin # Mercurial < 1.5 does not support footer template for '' - ActiveSupport::XmlMini.parse("#{io.read}")['log'] + ActiveSupport::XmlMini.parse("#{output}")['log'] rescue end end diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb index 1fad6e3f..59f577e6 100644 --- a/lib/redmine/scm/adapters/subversion_adapter.rb +++ b/lib/redmine/scm/adapters/subversion_adapter.rb @@ -65,6 +65,9 @@ module Redmine info = nil shellout(cmd) do |io| output = io.read + if output.respond_to?(:force_encoding) + output.force_encoding('UTF-8') + end begin doc = ActiveSupport::XmlMini.parse(output) #root_url = doc.elements["info/entry/repository/root"].text @@ -94,6 +97,9 @@ module Redmine cmd << credentials_string shellout(cmd) do |io| output = io.read + if output.respond_to?(:force_encoding) + output.force_encoding('UTF-8') + end begin doc = ActiveSupport::XmlMini.parse(output) each_xml_element(doc['lists']['list'], 'entry') do |entry| @@ -134,6 +140,9 @@ module Redmine properties = {} shellout(cmd) do |io| output = io.read + if output.respond_to?(:force_encoding) + output.force_encoding('UTF-8') + end begin doc = ActiveSupport::XmlMini.parse(output) each_xml_element(doc['properties']['target'], 'property') do |property| @@ -158,6 +167,9 @@ module Redmine cmd << ' ' + target(path) shellout(cmd) do |io| output = io.read + if output.respond_to?(:force_encoding) + output.force_encoding('UTF-8') + end begin doc = ActiveSupport::XmlMini.parse(output) each_xml_element(doc['log'], 'logentry') do |logentry| From 51d4785bde22ebc7bbde23dff0a9c5af526c5f94 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Thu, 3 Mar 2011 12:11:23 +0000 Subject: [PATCH 155/440] scm: mercurial: remove localtime from adapter (#4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4994 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 1f9153fa..d41ed7a3 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -210,7 +210,7 @@ module Redmine yield Revision.new(:revision => le['revision'], :scmid => le['node'], :author => (le['author']['__content__'] rescue ''), - :time => Time.parse(le['date']['__content__']).localtime, + :time => Time.parse(le['date']['__content__']), :message => le['msg']['__content__'], :paths => paths) end From bea085c3ba21e660cace018929b3ee3cc818c72e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Thu, 3 Mar 2011 12:44:14 +0000 Subject: [PATCH 156/440] scm: mercurial: convert copied file path encoding (#2664). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4995 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/mercurial_adapter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index d41ed7a3..6a2613fc 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -196,7 +196,9 @@ module Redmine as_ary(log['logentry']).each do |le| cpalist = as_ary(le['paths']['path-copied']).map do |e| - [e['__content__'], e['copyfrom-path']].map { |s| CGI.unescape(s) } + [e['__content__'], e['copyfrom-path']].map do |s| + scm_iconv('UTF-8', @path_encoding, CGI.unescape(s)) + end end cpmap = Hash[*cpalist.flatten] From fe4159fc99d3902155ee5f1dffc9ae09fc308b8c Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 4 Mar 2011 04:25:48 +0000 Subject: [PATCH 157/440] scm: mercurial: update test repository for path encoding (#2664). Mercurial (and also Git) treats file names as byte string. This mercurial test repository contains Latin-1 encoding path. Be careful on non Latin-1(CP1252) Windows. If your Windows is not Latin-1 Windows, in order to checkout(update) Latin-1 path, You need to use cygwin 1.7 and set LANG=en_US.ISO-8859-1. Please refer. http://mercurial.selenic.com/wiki/EncodingStrategy?action=recall&rev=6 Redmine mercurial adapter do not need to checkout(update) repository. Mercurial does not have "bare" repository such as Git. You can use "hg update null" for equivalent "bare" repository. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4996 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../repositories/mercurial_repository.hg | Bin 7104 -> 8902 bytes .../repositories_mercurial_controller_test.rb | 6 ++- .../scm/adapters/mercurial_adapter_test.rb | 37 +++++++++++++----- test/unit/repository_mercurial_test.rb | 14 ++++--- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/test/fixtures/repositories/mercurial_repository.hg b/test/fixtures/repositories/mercurial_repository.hg index c06844d235c3fad69b6e85f0b743f445f01f0cee..2b4eb62410643ae3c466665bab4f63dd0e7978e6 100644 GIT binary patch literal 8902 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 DiQ#Fz literal 7104 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 Project.find(3), :url => REPOSITORY_PATH) + @repository = Repository::Mercurial.create( + :project => Project.find(3), + :url => REPOSITORY_PATH, + :path_encoding => 'ISO-8859-1' + ) assert @repository @diff_c_support = true 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 d275798c..b5629841 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -10,10 +10,19 @@ begin REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository' + CHAR_1_HEX = "\xc3\x9c" + if File.directory?(REPOSITORY_PATH) def setup @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(REPOSITORY_PATH) @diff_c_support = true + + @tag_char_1 = "tag-#{CHAR_1_HEX}-00" + @branch_char_1 = "branch-#{CHAR_1_HEX}-00" + if @tag_char_1.respond_to?(:force_encoding) + @tag_char_1.force_encoding('UTF-8') + @branch_char_1.force_encoding('UTF-8') + end end def test_hgversion @@ -49,7 +58,7 @@ begin adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo) repo_path = adp.info.root_url.gsub(/\\/, "/") assert_equal REPOSITORY_PATH, repo_path - assert_equal '16', adp.info.lastrev.revision + assert_equal '24', adp.info.lastrev.revision assert_equal '4cddb4e45f52',adp.info.lastrev.scmid end end @@ -97,7 +106,7 @@ begin def test_diff_made_by_revision if @diff_c_support - [16, '16', '4cddb4e45f52'].each do |r1| + [24, '24', '4cddb4e45f52'].each do |r1| diff1 = @adapter.diff(nil, r1) assert_equal 5, diff1.size buf = diff1[4].gsub(/\r\n|\r|\n/, "") @@ -219,24 +228,32 @@ begin end def test_tags - assert_equal ['tag_test.00', 'tag-init-revision'], @adapter.tags + assert_equal [@tag_char_1, 'tag_test.00', 'tag-init-revision'], @adapter.tags end def test_tagmap - tm = { 'tag_test.00' => '6987191f453a', - 'tag-init-revision' => '0885933ad4f6' } + tm = { + @tag_char_1 => 'adf805632193', + 'tag_test.00' => '6987191f453a', + 'tag-init-revision' => '0885933ad4f6', + } assert_equal tm, @adapter.tagmap end def test_branches - assert_equal ['default', 'branch (1)[2]&,%.-3_4', 'test-branch-00'], - @adapter.branches + assert_equal ['default', @branch_char_1, + 'test_branch.latin-1', 'branch (1)[2]&,%.-3_4', 'test-branch-00'], + @adapter.branches end def test_branchmap - bm = { 'default' => '4cddb4e45f52', - 'branch (1)[2]&,%.-3_4' => '933ca60293d7', - 'test-branch-00' => '3a330eb32958' } + bm = { + 'default' => '4cddb4e45f52', + @branch_char_1 => 'c8d3e4887474', + 'test_branch.latin-1' => 'c2ffe7da686a', + 'branch (1)[2]&,%.-3_4' => '933ca60293d7', + 'test-branch-00' => '3a330eb32958' + } assert_equal bm, @adapter.branchmap end diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index 271ffe43..9c3032bf 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -25,7 +25,11 @@ class RepositoryMercurialTest < ActiveSupport::TestCase def setup @project = Project.find(3) - @repository = Repository::Mercurial.create(:project => @project, :url => REPOSITORY_PATH) + @repository = Repository::Mercurial.create( + :project => @project, + :url => REPOSITORY_PATH, + :path_encoding => 'ISO-8859-1' + ) assert @repository end @@ -33,8 +37,8 @@ class RepositoryMercurialTest < ActiveSupport::TestCase def test_fetch_changesets_from_scratch @repository.fetch_changesets @repository.reload - assert_equal 17, @repository.changesets.count - assert_equal 25, @repository.changes.count + assert_equal 25, @repository.changesets.count + assert_equal 32, @repository.changes.count assert_equal "Initial import.\nThe repository contains 3 files.", @repository.changesets.find_by_revision('0').comments end @@ -47,7 +51,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase assert_equal 3, @repository.changesets.count @repository.fetch_changesets - assert_equal 17, @repository.changesets.count + assert_equal 25, @repository.changesets.count end def test_isodatesec @@ -170,7 +174,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase @repository.fetch_changesets @repository.reload changesets = @repository.latest_changesets('README', nil) - assert_equal %w|8 6 1 0|, changesets.collect(&:revision) + assert_equal %w|17 8 6 1 0|, changesets.collect(&:revision) path = 'sql_escape/percent%dir/percent%file1.txt' changesets = @repository.latest_changesets(path, nil) From 3fadaf3c855c748c6ba69825a2da66833ac79bad Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 4 Mar 2011 08:07:53 +0000 Subject: [PATCH 158/440] scm: mercurial: update test repository for path contains space (#2664, #4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4997 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../repositories/mercurial_repository.hg | Bin 8902 -> 9702 bytes .../scm/adapters/mercurial_adapter_test.rb | 22 +++++++++++------- test/unit/repository_mercurial_test.rb | 8 +++---- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/test/fixtures/repositories/mercurial_repository.hg b/test/fixtures/repositories/mercurial_repository.hg index 2b4eb62410643ae3c466665bab4f63dd0e7978e6..ef65dfeee43a710729d86db1b6a655f1a6264e57 100644 GIT binary patch literal 9702 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 literal 8902 zcmaiWRa6uV)a}q+1Cj#_Fmw+f9YYSKbazWhN~$w-J3}`^w;-L;F?0(8N=bu+ilXTM z{de8hyY5+Q?{oIk*-!f%xR$t>s+EVVILwmA*z#KA=|2FD;p>0@zuE!6V-Hm`%juaN ztfA85iPzZKMi|gZ5+W1;lu_@t#8o30>rgMm0000b0&noY1|W#ZMCH3Y6BoxAOESAY zuErGe=!83XtQ0TS9xSY2Pn|Up3&z96%f|YW;usHVw<;bIWV+-xX5O;mJTX05eKDRm z9L=dPl7nUZg=j;P4E|#mN0M6f@yd6}kJ0)7=KoeOQ~WRe?*ssN{D=SK{}pQb02pj2>SKeqlKL;|5E#*r-62k=xa8++)j45msh>+3)D%%fV0 z&+y>C&ws;*EdZ9(g@@-oHC_pSvlOmo{9Vyt@e7ohaD~P2gxNz;O7dHAeo37o*UCb; zCtE&Z;jz9Nn2L4o^{%hjq9%ZRa{VQH9(h%EDt~`=CDx(nrt*u@E9DI7bG$+S$zE-Y zWo=l!scp$x9D%P5mkQ8UD$B4zR%h!79>S{)I9Vk`ASbHszjbO|0n z_vgnp#Nn5G@~`YZ93s9LuUqfp7Z5WsIE(ep=Z-#B?qz#+BqncY>msW#zdw6fTpNA~ zvL+-ucA{|JcF}8GqveKP<90p&(YfjRRHWL!s?q1@al7Pb0b%(|*+iy~o9jdch0ar7 ze6|P@Kc9KxNVr?KIsEMS^Ofv4?z7(djl8CiUr_j8^QR}1fvF+vOsh1G1sp>gXL5K@ zNE9h;;YDWnXVU3EhWIbtUD>&*iARx8j1FT@1Zmp|%=~RQ`E|*K2Nw}Bj~Ra?;yT%*($V(Y{OO9gUr|wNq#rRb;C*@QdQC}v zJWFbTikr61@a(@AM~WOIERHC$O(@(XC7oc(fjZ=~IF?v8!NKMbTI)yYSkOLt5E(k! zqVBH5RV;II(L+jdvUhE?*G2Fdf(^qX-fs5Z;5O8v%u%Am_#LaTapHlQnB$uNz4ss& zkIRd~3(qB%2M_8X6Un;7>|qWh;Vl6X%q6FbHMZ5HZ>N2@EMtW&^9_DwaiTE z+58HBe%{H^@-`8IcoO{O)96t}j`S`GPro{$uVbhhy(V+d<^gV*c59rnc$h`nRA@e5 z`f4d=V%dEYe{oN86YhsjkxbH}ahB$*tDAXQe#k$HekT%d@z0{^MlB2I(R}D&=yiKX z3sj<@%>m5{tXPZh$tC)WcI~l{t{40bAQ61H=gJqN4Cca$+jHbU?Yh{eRqQGu@~2Rf zZH}J(r5URAsXSuLIky!AOGx^_-wBj<36y-B-GN)V(O!rhJTZn4or7N$54S+TB@1x5aQi=(n zt{H2zNE&0c@Yno!%m<+5$Za5CP@}?8WDqvvgwX6%%)sf1mZ*Tu3xC3^9_FKp6l70+ zyV5F9)6hE~#O@A3Q^hfOsmD)jl2&pQ?K`uBanM7N##Wd#R;Q$#b-Kvt%f2}Wk-c9u zl)P5Jed>oay4lXJN=6UI#iMV{y{Qf)lwqN-%C48`Xe2emJuWEIB!2j#?Wg3+eRH3R zd=g0WXkvwFxQdQ`nV?b44zwOw{jE>1KEhaiiICH(@o(1J$2ka` zYdtCP*Kvva7HcfwjL88<7>`773a?X`?8w-S}A zt>4vc(myRekIH`XeljcYji29>I5wSp*JshpGW%u`!>6LU^h9;N>x7iY4I!?C#ffs5 z8+cYiuAU>pf0Rzo>K2Cs!^5fLY;DCov{5$d`oy8vB2>MCv1X!FTFjY*V>6RVyhUn> zCgnW~Q*14nYt6&@h7)lnn`f=E<+>#SWrgAY>L!2#QX5Z6kq z!&%l!2qfK_=Q$vCq2sS)O_@y|9p=#RTX0Hoi31@?wR-z9 zcLLDlOmUb@vmUpQ%2qtuXeNn08i~C9aZX3qgpZCdRBPs~yuNSQ>={jdZ!%#mYmQ`z2VLiQhdri=*gt!5L}m#} ztkv)+F22;kk{qoRt3KBQF^Dn#VaI zOK>4~v&9O@Mi2%KyhDnTJ`fyJB{-cSv7SBRFP^lP;40Hp6ITY%zG1X}^6teXa;z^n zqbc7#*getS0)I>9_As!}>37fz0=1P%1$?o7$V(%TKa=n**`1GWiTk zdQo~&YkZWDn}xDO!^AR@itJ+>+~HC1qL@#FUh7pB_9Ff^w(B`j1%&Ezz_v;i85z>`uE&TZb4J3z5FbsWLS9K zIX1ty2JXg<(^V#Bg3!k#i-T{Rv$P3xG6hsyqDWibvCaAIHZa478-FNM9sT+n@JsC_ zdPdu_BPTP0YXpz2PvzFE%x)n;k&$fgDZB?u32>EvZ?n7N9@A+Usgc1jY zOak^B+cS!o22|R4o$gmx+M~#xn0_=W7wfPvy6wG)B7VtsWku;J@Xn6F-Dph&&ch zd>q~|5;iAPB*W)@Z8UsM; zyb26LF~_54&Dp5I3nAq0DF^DL)sAF_-|B9dGN6GVmRd(Dy3njXc@Xz+03Ab{QDzWN zG^CUGqM^4}UJJ6@T;L^^$Kf^QH&ozwLO63qle{e3?yhV)JmR0WT6nu`05l4SYmWN!#pbBE#Zjb9>75oIS3yh9$F;1ofh(ONH?m zwa8PPr0Pgu73P3Z{SaWBnZDXtFFrkp=At!EL&|CJvn+os?a1-;OUybFSuKL4I{kvVo4zg&~qlGAQ*4Kv*|Jq5iva#uikPv@j5;H}Zui5nGh zJf>$&rPa0Z3h2t@qEWPvx&808`O^!t^-5COIb8^TyO!ecf;qNv^-%d-U&W!tF}4kC zCgAj(JXVToOE2o#VnwpGu)zqLI411|B|SR+9f#c{t~G%aOeez99WZDK4`x(YtLYJ2 z7&M$}IZC-$1ZL9z(9AS=Cg!K9prSAd{X4vC-<(GCtL(McnV%4!VEsOryp`di!@WT zccmD*lf{M%RLp{qN>Qrzj6_;W`&dQ6kEK%eozND0TS_w`O1DT?ug*2}3pl#kHi_|D zS$UhY8>%zmP0B#OffC0zuiJ0xE`IM@j!l^d48b890khXJBEvd{6>yCO)sK<%UGg3h z1#(?IBUO0qw0tKPmAYg=tB*HKR4>vRi>WUFDAG3&@?n7s%?v*5(hs$Ec97ags)rqU z++ILO!8V=9n?e8QZB(gegVrx%raF{vC>mM%7TAi$O+M8IQ#0g%-#3S&5WU5V;Y*`z z$l~d^1x4YotqlZn%f{YXqBaS%pgzU1YABcFR4B32%r|VkQ|}PUk-2wpPhN**9X&mG2o15pEow=l61o^vR~1Kv+}~sRIHiqV1Uwmrgb9u|G|+Hzby9qxWk|@1XEdun zdUn-K)5&k4!z4#KkG|nzCa0q?aEZ%myEn&~Jx0l<#2(xUEk)Ri%jRS|4waZ+v{#qE znW%rTTPQm=-#`;~_lF*#}kskG&)S()pcp?!&No9PykpVL0t@_cq;r}-4c zi>$0A%<#gk$O>D03YUia8!GfiMKY3UMg!4ySZtn2Qsu{bi z#oFN=1+oqIXj#`h3&gI+SO+P8|AzCCe{0IkMyB(wa;%I^oDBD=Vn}trpg=;p2QAac z7B#f?k>A71)kCfc>wz9RDErheANI+>G&3M(n=$Qq+6TOo{9!OcG~sobVSGRy4c``f zir+xw$5}#^k&a&ph#)`0Hb{h>E4yCmJmH|3YLpV>FqzYrdaH#!!Jz3!DvRR;ypfU1 zV)(w|Qzmb*Ae+nCmkjkEtxlOxNw55*m4+xLIJ>#KRpbxp%!rk6jdlo@vW%ccxsHDm0y-ehX@x zokq~CEavFyn9zUcH<#fs@8dq)lPxdMglW2^B>GwY5LoQq2l4eD9urkN; zkKogR_7yO>q|76`@2!g!$$ACn;(OYSivOtjnKuHJ>A5IssKJMk}k@m@fe^l|b{ z!7qt3-ty!}nR5-mOe^iOkje_Z*k8^N2@b5;3(Eb~BJJse(;1 zxz&jfdD(a!M(VT{Neqb(&h21n|5-vT&7+W-RKqQ~c8A9uBS%D%g^PO{o2vOECdpp< zoAW}t?jnLy{-^i{z}fo?d>j^W`0mj;q5aumJwvkq!6kZ$Qqv6-nW7fmOPS`sA>ZPA zl1Ok~_#3~7Fxy(2{WoK+(0yX&m`8n#p*FPKKJxweE>jPco7@n1ZY&@-Y15S=Y4 z0C`nFw;sacou{=31V7nJ!WWmX`jzt(RJ6>Uyp@{OKHOdr$1Re^9&^)@48+Gu99%Hx81M4yn$Pe=!yreXT+*0)?- zTA!(=M;_v;*y#%~N}O(ijMn7vV(;htbvWO=r~rd zahXV@GjZ8*LSRVojo?o+l$Obfy>m|en?1H68iGD|z0z^tGTBio2(O z`JKe`6YvJj$f%@I`w`7pE=RfTarjB@FPJ2(s6pJx0~2iC>3uUFHMu8QOk2~Je?c}c z$Q1eqfTnG#7DqII*1{0&Y4y8XX;S;NWW_??Y;g9vWO4oCyvqo@)RJ8Y9rp`WT)qun z=kbBrzBfOLA=`^3&QsTc5tKsJ$Fi*wZE<^W=LWSc5knlNDrlF)ToZUD-9CMEU&_JM zrw^=a?nV~WoV%$ALuDE=>IuxC18;@E0=oUlP!1NdXF0_1)5EbnfOUPral1&wHC&% zFrI2_w&2e5AIum|D5%`*pjbSRY`>f&XBwo$Djgz;4Ro%HbxqAVWE!{=q~*AB19_ot zpxIbtu3HrQvV5)cw4>p))-@Hsgi69bFZ^3B#riaG)&ID3HI+y+%I!12lXbR3w^Q|wGHZM-4G(G1Xgt){Yj#EcwGiPOd z{@H#KS~q{7Zm!%Qbhc%-4J*9UiY8*MVP)OkN8>cl`sE38#FzRRL4cZwy~)3w zj1Sw-)yHzpHP9&yE;#+QYITrPqgMasUW){q0!0(3gJYB_&;T~LJ4J9UP8;Qyo@qdD zap2eTs2=Wv+0*4$2g}?>zPfto&yiv&lS}x_zJu-HT`~`enq|t1Td-vqA9T{3v7`R@ zrR8KqorxPY#U0Ff_zL>H{I76%VJ&SOS+v3uC~f9|O(y-stk<9i+TlPwxRo}~$u6IM zClm5J{7%c8ydPO7SfwM>3~nDvlA2Vf$y9{%f-$!Ei>|XCmRvPyk{l{58(5Hn1}dwu2Upngsb+6lKtmUnPv-?<1IEU@9KnSast@ zML!^o5xFcpo~|WynXTcASSCpvQ16Hrk_d14g1lJ#oIF4_Z6m~MtSN>Gy|0hY#b%GT zM2j8ZG3Tkm&agCukFHEvu7}T|s#!1rFgc>=pu%YsCiCG934wQ_jRVnFeACHrQ$>No z?Bn$&til(U&FJX_LZYlO*<-eNvYD}m?OV61$2mYd%iA|77g3Ks?j;}Kuy-pV(Bd$B zi2Q&IbCKUDi}L;kC}ig}VNrX%y1=X7aJ^s0gV+^)dBebP8le@jH9$OfO}Qd3{0QYl z_4D9QA(A`n!F%NQZnpR-M?7FeOl&;#0JR&F*n%W@O0z{Wo!I3_ye3`sHh>07V1$D* zdBVd4#m#w+7w%5&kSCxPYNUb~?zW_Zd5l^gq7dVN`@LB-?MIkF3HTswmz4>?4PhfY zTSr6mU=(z?8SZok?;aYRuh;{eYuI?g9P6K9r;X$S9j7?qzDJ|7G&gIMS^trVUZ%gr;#fSM znRU4zUL-~dlFJQV?~Cxug1^gxRkHTf^x$J?btT;gg?kYGyMbkUc692x7alc zY{+Bmv^T>Hk|bxuX)g+T_XJB81vUkK2vv?V#xk{@zf>GmBI{;9iayE z@UGn1elD2lc5mUedbu&A+bD)~*h99lR_iWj^AWg^ITYG4@rs!X=+k_&PLe`Fzu$$G*`9zZ3#X z+-uBGzwmA~ybD31sjty%v`x8xvzcGs2)(fr|FcuWMJ!G1zIaVuZHue{@3XbTx+Udq z6Wg1U*&g8SvX)?3t3ZHSxsl6UD}~wI!~%L^+4Q%^pf#6POY-Y(Z*eD?`WM}EsV8C# z6CHr2_JAVDDxnH-59#_r*A|_})_{a`>Ina=&6lxVjX2#g56MuS-9#}rgRh~bGQ5!5 zPLmojiA&Q!eQ2_P%#CN^6ZHepILdI#<5u|UKGyF=sQn7)k4mJDtfLwtzH8#rO4{v; zMfG$3pQP+09-#>)VCQe?i2hN#(r;Y5yJpNv4K7~=g~M(M#$yk+sw5r%SZZMTeT_ETP{d@RkAB=)MI1%|D@?wsf!t4{wiAbY-; zpnx&b6j38sSVAY|7e-H-AJh+@mu@5)=d)Pw%9DVIgeBm;9;xEkj+QkVZ$!7K=byof$K>!3S2KSSdqXu3 z8u%K6?BL9WA%vZ$E%Jm2{wZWn&*Y@Vw3zF-PApt#5U); zjk5ypar`@{bYaHIm784Sx}Iiy`;bGK3DF|)bT*ce+HuXVXg`1DyXL!HU$>nvHs!$A=dskK3+F2(Z7E__G(tYawJ#Wx(ewAuz7hGrKr=x@U#LSI0S2ISI`KRS3lfu&EY2HuaM7Dj?$x8XpC<^#_`#Jo@p#7 zae4?pMoWKT6TebjeaH9lFM<4 zK%%L5=wu*T{uD+lq!&W@SSY1$@N=cbr^W8V8;VrMlFc_d&HNO|iP7D#8VpX8DQFYD zx%YE2xdi(9lD^HOax&-s!d5``W7caem(TitkcUWTNi&|N;RC%Ncp&5a@9~s8;%xgh zuV{F8?O?N^;+?t%=5Ln$Oj18LjqB{)n^}&%|3S=!Va;u?UyaUZa_(|?Rfe)$jb!ME zC@RFOR|dH=KX9WL|R=VDm9c zH|SP{ng{lgaD%+f*Tu;x^q=9PMZ!-dhxb@p?gBR2#9LqE_O^7yDQao{vNb7lw7q|t z_92j*7nJCaoUqGd){Aqb`7E7C|0%6=?R&7gKiwmjOsE3BFDFPp`t&zJym^2J*^X8+ z*+(|6{u(j-x@5I;DhCvET8Z*ga3!|^)=aAT-ojD zduDZ^lg+=eCio{NG!+V^eZK+juP0v)y^uZb#j9|ba6k7RIk+h>dV?J`xZ+8z z`ugS{-h}s#KfyJh)Ax&CH{IvF>b@V%^;}01+VM7bG>5uu%JdGzQ)FIUFuvvPstA=Y z58A8+ugKbQ4~}x}&k}tAkBdbyd5I+s=!UER99!*zz5d)_qq#mGHUFaw{pfZnYrmV=8^5;z9c2wq-IcD)6qsLh6do6tsh#!9cLi}l>tz8%($G>w{-Jt!IYt+jg%){z3KeJG4V+PuYdjz DiQ#Fz 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 b5629841..8e971ec9 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -58,8 +58,8 @@ begin adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo) repo_path = adp.info.root_url.gsub(/\\/, "/") assert_equal REPOSITORY_PATH, repo_path - assert_equal '24', adp.info.lastrev.revision - assert_equal '4cddb4e45f52',adp.info.lastrev.scmid + assert_equal '26', adp.info.lastrev.revision + assert_equal '3ae45e2d177d',adp.info.lastrev.scmid end end @@ -241,18 +241,22 @@ begin end def test_branches - assert_equal ['default', @branch_char_1, - 'test_branch.latin-1', 'branch (1)[2]&,%.-3_4', 'test-branch-00'], - @adapter.branches + assert_equal [ + 'default', + 'branch (1)[2]&,%.-3_4', + @branch_char_1, + 'test_branch.latin-1', + 'test-branch-00', + ], @adapter.branches end def test_branchmap bm = { - 'default' => '4cddb4e45f52', - @branch_char_1 => 'c8d3e4887474', + 'default' => '3ae45e2d177d', 'test_branch.latin-1' => 'c2ffe7da686a', - 'branch (1)[2]&,%.-3_4' => '933ca60293d7', - 'test-branch-00' => '3a330eb32958' + 'branch (1)[2]&,%.-3_4' => 'afc61e85bde7', + 'test-branch-00' => '3a330eb32958', + @branch_char_1 => 'c8d3e4887474', } assert_equal bm, @adapter.branchmap end diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index 9c3032bf..d4053e1f 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -37,8 +37,8 @@ class RepositoryMercurialTest < ActiveSupport::TestCase def test_fetch_changesets_from_scratch @repository.fetch_changesets @repository.reload - assert_equal 25, @repository.changesets.count - assert_equal 32, @repository.changes.count + assert_equal 27, @repository.changesets.count + assert_equal 34, @repository.changes.count assert_equal "Initial import.\nThe repository contains 3 files.", @repository.changesets.find_by_revision('0').comments end @@ -51,7 +51,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase assert_equal 3, @repository.changesets.count @repository.fetch_changesets - assert_equal 25, @repository.changesets.count + assert_equal 27, @repository.changesets.count end def test_isodatesec @@ -174,7 +174,7 @@ class RepositoryMercurialTest < ActiveSupport::TestCase @repository.fetch_changesets @repository.reload changesets = @repository.latest_changesets('README', nil) - assert_equal %w|17 8 6 1 0|, changesets.collect(&:revision) + assert_equal %w|26 17 8 6 1 0|, changesets.collect(&:revision) path = 'sql_escape/percent%dir/percent%file1.txt' changesets = @repository.latest_changesets(path, nil) From 13d13c426d9d4030043285289c0ffdfd7145c0c0 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 4 Mar 2011 08:08:13 +0000 Subject: [PATCH 159/440] scm: mercurial: add unit adapter test repository for path contains space (#2664, #4455). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4998 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../redmine/scm/adapters/mercurial_adapter_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 8e971ec9..b89caa5b 100644 --- a/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb @@ -261,6 +261,18 @@ begin 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 + end + end + private def test_hgversion_for(hgversion, version) From 7006fe1df815372b4cd73992c531362928e5c359 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 4 Mar 2011 08:08:32 +0000 Subject: [PATCH 160/440] scm: mercurial: additional unit model tests for path encoding (#2664). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4999 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_mercurial_test.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index d4053e1f..6d8d7a47 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -23,6 +23,8 @@ class RepositoryMercurialTest < ActiveSupport::TestCase # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository' + CHAR_1_HEX = "\xc3\x9c" + def setup @project = Project.find(3) @repository = Repository::Mercurial.create( @@ -31,6 +33,10 @@ class RepositoryMercurialTest < 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 if File.directory?(REPOSITORY_PATH) @@ -115,6 +121,13 @@ class RepositoryMercurialTest < ActiveSupport::TestCase assert_equal 'A', c2[0].action assert_equal '/README (1)[2]&,%.-3_4', c2[0].path assert_equal '/README', c2[0].from_path + + cs3 = @repository.changesets.find_by_revision('19') + c3 = cs3.changes + 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 end def test_find_changeset_by_name From cd9cf95d9ab84f7c43d2d1f67f3dd7f1c836076e Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 4 Mar 2011 11:07:58 +0000 Subject: [PATCH 161/440] scm: mercurial: add path encoding tests in functional test (#2664, #4050). TODO: This test fails in Ruby 1.9 and Encoding.default_external is not UTF-8. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5000 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../repositories_mercurial_controller_test.rb | 90 ++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/test/functional/repositories_mercurial_controller_test.rb b/test/functional/repositories_mercurial_controller_test.rb index 3960285f..15c62167 100644 --- a/test/functional/repositories_mercurial_controller_test.rb +++ b/test/functional/repositories_mercurial_controller_test.rb @@ -26,6 +26,9 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository' + CHAR_1_HEX = "\xc3\x9c" + + ruby19_non_utf8_pass = (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8') def setup @controller = RepositoriesController.new @@ -39,9 +42,18 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase ) assert @repository @diff_c_support = true + @char_1 = CHAR_1_HEX.dup + if @char_1.respond_to?(:force_encoding) + @char_1.force_encoding('UTF-8') + end end - if File.directory?(REPOSITORY_PATH) + if ruby19_non_utf8_pass + puts "TODO: Mercurial functional test fails in Ruby 1.9 " + + "and 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) def test_show get :show, :id => 3 assert_response :success @@ -99,6 +111,25 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase end end + def test_show_directory_latin_1 + @repository.fetch_changesets + @repository.reload + [21, '21', 'adf805632193'].each do |r1| + get :show, :id => 3, :path => ['latin-1-dir'], :rev => r1 + assert_response :success + assert_template 'show' + + assert_not_nil assigns(:entries) + assert_equal ["make-latin-1-file.rb", + "test-#{@char_1}-1.txt", + "test-#{@char_1}-2.txt", + "test-#{@char_1}.txt"], assigns(:entries).collect(&:name) + changesets = assigns(:changesets) + assert_not_nil changesets + assert_equal %w(21 20 19 18 17), changesets.collect(&:revision) + end + end + def test_changes get :changes, :id => 3, :path => ['images', 'edit.png'] assert_response :success @@ -116,6 +147,18 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase :attributes => { :class => 'line-num' }, :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ } end + + def test_entry_show_latin_1 + [21, '21', 'adf805632193'].each do |r1| + get :entry, :id => 3, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1 + assert_response :success + assert_template 'entry' + assert_tag :tag => 'th', + :content => '1', + :attributes => { :class => 'line-num' }, + :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ } + end + end def test_entry_download get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb'], :format => 'raw' @@ -172,6 +215,19 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase end end + def test_diff_latin_1 + [21, 'adf805632193'].each do |r1| + get :diff, :id => 3, :rev => r1 + assert_response :success + assert_template 'diff' + assert_tag :tag => 'th', + :content => '2', + :sibling => { :tag => 'td', + :attributes => { :class => /diff_in/ }, + :content => /It is written in Python/ } + end + end + def test_annotate get :annotate, :id => 3, :path => ['sources', 'watchers_controller.rb'] assert_response :success @@ -212,6 +268,38 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase end end + def test_annotate_latin_1 + [21, '21', 'adf805632193'].each do |r1| + get :annotate, :id => 3, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1 + assert_response :success + assert_template 'annotate' + assert_tag :tag => 'th', + :content => '1', + :attributes => { :class => 'line-num' }, + :sibling => + { + :tag => 'td', + :attributes => { :class => 'revision' }, + :child => { :tag => 'a', :content => '20:709858aafd1b' } + } + assert_tag :tag => 'th', + :content => '1', + :attributes => { :class => 'line-num' }, + :sibling => + { + :tag => 'td' , + :content => 'jsmith' , + :attributes => { :class => 'author' }, + + } + assert_tag :tag => 'th', + :content => '1', + :attributes => { :class => 'line-num' }, + :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ } + + end + end + def test_empty_revision @repository.fetch_changesets @repository.reload From ac58816e9fdb18123be0555951473bd6bc3710f4 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 4 Mar 2011 13:39:00 +0000 Subject: [PATCH 162/440] scm: mercurial: add path encoding select box at setting (#2664). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5001 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/repositories_helper.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 23899a88..c0d5909c 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -205,7 +205,11 @@ module RepositoriesHelper def mercurial_field_tags(form, repository) content_tag('p', form.text_field(:url, :label => :label_mercurial_path, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) + - '
    local repository (e.g. /hgrepo, c:\hgrepo)' ) + '
    local repository (e.g. /hgrepo, c:\hgrepo)' ) + + content_tag('p', form.select( + :path_encoding, [nil] + Setting::ENCODINGS, + :label => 'Path encoding') + + '
    Default: UTF-8') end def git_field_tags(form, repository) From 2fa11b21681dfb7f5a928db8bcb4fe13ce4e3b60 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 4 Mar 2011 14:03:19 +0000 Subject: [PATCH 163/440] scm: mercurial: add changesets order test in unit model test (#5357). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5002 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/repository_mercurial_test.rb | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/unit/repository_mercurial_test.rb b/test/unit/repository_mercurial_test.rb index 6d8d7a47..6e7938f6 100644 --- a/test/unit/repository_mercurial_test.rb +++ b/test/unit/repository_mercurial_test.rb @@ -212,6 +212,46 @@ class RepositoryMercurialTest < ActiveSupport::TestCase changesets = @repository.latest_changesets(path, nil) assert_equal %w|13 12 9|, changesets.collect(&:revision) end + + def test_previous + @repository.fetch_changesets + @repository.reload + %w|26 3ae45e2d177d 3ae4|.each do |r1| + changeset = @repository.find_changeset_by_name(r1) + %w|25 afc61e85bde7 afc6|.each do |r2| + assert_equal @repository.find_changeset_by_name(r2), changeset.previous + end + end + end + + def test_previous_nil + @repository.fetch_changesets + @repository.reload + %w|0 0885933ad4f6 0885|.each do |r1| + changeset = @repository.find_changeset_by_name(r1) + assert_nil changeset.previous + end + end + + def test_next + @repository.fetch_changesets + @repository.reload + %w|25 afc61e85bde7 afc6|.each do |r2| + changeset = @repository.find_changeset_by_name(r2) + %w|26 3ae45e2d177d 3ae4|.each do |r1| + assert_equal @repository.find_changeset_by_name(r1), changeset.next + end + end + end + + def test_next_nil + @repository.fetch_changesets + @repository.reload + %w|26 3ae45e2d177d 3ae4|.each do |r1| + changeset = @repository.find_changeset_by_name(r1) + assert_nil changeset.next + end + end else puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end From 6f5707c2b54d5a3ced1f63c31e67f863f1b46a37 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 4 Mar 2011 14:32:58 +0000 Subject: [PATCH 164/440] Adds email notifications support for news comments (#2074). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5003 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/news_controller.rb | 6 +++-- app/models/comment_observer.rb | 24 +++++++++++++++++++ app/models/mailer.rb | 22 +++++++++++++++-- app/models/news.rb | 11 ++++++++- .../mailer/news_comment_added.text.html.rhtml | 5 ++++ .../news_comment_added.text.plain.rhtml | 6 +++++ app/views/news/show.rhtml | 1 + config/environment.rb | 2 +- config/locales/en.yml | 1 + config/locales/fr.yml | 1 + lib/redmine/notifiable.rb | 1 + test/unit/comment_test.rb | 13 ++++++++-- test/unit/lib/redmine/notifiable_test.rb | 8 +++---- test/unit/mailer_test.rb | 14 ++++++++--- 14 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 app/models/comment_observer.rb create mode 100644 app/views/mailer/news_comment_added.text.html.rhtml create mode 100644 app/views/mailer/news_comment_added.text.plain.rhtml diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb index e7c643e9..bc7eabb5 100644 --- a/app/controllers/news_controller.rb +++ b/app/controllers/news_controller.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 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 @@ -25,6 +25,8 @@ class NewsController < ApplicationController before_filter :find_optional_project, :only => :index accept_key_auth :index + helper :watchers + def index case params[:format] when 'xml', 'json' diff --git a/app/models/comment_observer.rb b/app/models/comment_observer.rb new file mode 100644 index 00000000..fc008942 --- /dev/null +++ b/app/models/comment_observer.rb @@ -0,0 +1,24 @@ +# Redmine - project management software +# Copyright (C) 2006-2011 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. + +class CommentObserver < ActiveRecord::Observer + def after_create(comment) + if comment.commented.is_a?(News) && Setting.notified_events.include?('news_comment_added') + Mailer.deliver_news_comment_added(comment) + end + end +end diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 8ad2c179..fbda2180 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 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 @@ -154,6 +154,24 @@ class Mailer < ActionMailer::Base :news_url => url_for(:controller => 'news', :action => 'show', :id => news) render_multipart('news_added', body) end + + # Builds a tmail object used to email recipients of a news' project when a news comment is added. + # + # Example: + # news_comment_added(comment) => tmail object + # Mailer.news_comment_added(comment) => sends an email to the news' project recipients + def news_comment_added(comment) + news = comment.commented + redmine_headers 'Project' => news.project.identifier + message_id comment + recipients news.recipients + cc news.watcher_recipients + subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}" + body :news => news, + :comment => comment, + :news_url => url_for(:controller => 'news', :action => 'show', :id => news) + render_multipart('news_comment_added', body) + end # Builds a tmail object used to email the recipients of the specified message that was posted. # diff --git a/app/models/news.rb b/app/models/news.rb index 00729f06..7f8c7310 100644 --- a/app/models/news.rb +++ b/app/models/news.rb @@ -1,5 +1,5 @@ # Redmine - project management software -# Copyright (C) 2006-2008 Jean-Philippe Lang +# Copyright (C) 2006-2011 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 @@ -28,6 +28,9 @@ class News < ActiveRecord::Base acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} acts_as_activity_provider :find_options => {:include => [:project, :author]}, :author_key => :author_id + acts_as_watchable + + after_create :add_author_as_watcher named_scope :visible, lambda {|*args| { :include => :project, @@ -42,4 +45,10 @@ class News < ActiveRecord::Base def self.latest(user = User.current, count = 5) find(:all, :limit => count, :conditions => Project.allowed_to_condition(user, :view_news), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") end + + private + + def add_author_as_watcher + Watcher.create(:watchable => self, :user => author) + end end diff --git a/app/views/mailer/news_comment_added.text.html.rhtml b/app/views/mailer/news_comment_added.text.html.rhtml new file mode 100644 index 00000000..ef2be0f6 --- /dev/null +++ b/app/views/mailer/news_comment_added.text.html.rhtml @@ -0,0 +1,5 @@ +

    <%= link_to(h(@news.title), @news_url) %>

    + +

    <%= l(:text_user_wrote, :value => h(@comment.author)) %>

    + +<%= textilizable @comment, :comments, :only_path => false %> diff --git a/app/views/mailer/news_comment_added.text.plain.rhtml b/app/views/mailer/news_comment_added.text.plain.rhtml new file mode 100644 index 00000000..aadbc37c --- /dev/null +++ b/app/views/mailer/news_comment_added.text.plain.rhtml @@ -0,0 +1,6 @@ +<%= @news.title %> +<%= @news_url %> + +<%= l(:text_user_wrote, :value => @comment.author) %> + +<%= @comment.comments %> diff --git a/app/views/news/show.rhtml b/app/views/news/show.rhtml index 0dc3fe35..28db44e9 100644 --- a/app/views/news/show.rhtml +++ b/app/views/news/show.rhtml @@ -1,4 +1,5 @@
    +<%= watcher_tag(@news, User.current) %> <%= link_to(l(:button_edit), edit_news_path(@news), :class => 'icon icon-edit', diff --git a/config/environment.rb b/config/environment.rb index 91dfaa42..00e81517 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -36,7 +36,7 @@ Rails::Initializer.run do |config| # Activate observers that should always be running # config.active_record.observers = :cacher, :garbage_collector - config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer + config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer, :comment_observer # Make Active Record use UTC-base instead of local time # config.active_record.default_timezone = :utc diff --git a/config/locales/en.yml b/config/locales/en.yml index c0fb8fca..3649fe23 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -537,6 +537,7 @@ en: label_news_latest: Latest news label_news_view_all: View all news label_news_added: News added + label_news_comment_added: Comment added to a news label_settings: Settings label_overview: Overview label_version: Version diff --git a/config/locales/fr.yml b/config/locales/fr.yml index b3a60ba7..356f3799 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -539,6 +539,7 @@ fr: label_news_latest: Dernières annonces label_news_view_all: Voir toutes les annonces label_news_added: Annonce ajoutée + label_news_comment_added: Commentaire ajouté à une annonce label_settings: Configuration label_overview: Aperçu label_version: Version diff --git a/lib/redmine/notifiable.rb b/lib/redmine/notifiable.rb index 71d1ba50..37d4a407 100644 --- a/lib/redmine/notifiable.rb +++ b/lib/redmine/notifiable.rb @@ -14,6 +14,7 @@ module Redmine notifications << Notifiable.new('issue_status_updated', 'issue_updated') notifications << Notifiable.new('issue_priority_updated', 'issue_updated') notifications << Notifiable.new('news_added') + notifications << Notifiable.new('news_comment_added') notifications << Notifiable.new('document_added') notifications << Notifiable.new('file_added') notifications << Notifiable.new('message_posted') diff --git a/test/unit/comment_test.rb b/test/unit/comment_test.rb index 43265c47..02be8fc5 100644 --- a/test/unit/comment_test.rb +++ b/test/unit/comment_test.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 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 @@ -31,6 +31,15 @@ class CommentTest < ActiveSupport::TestCase @news.reload assert_equal 2, @news.comments_count end + + def test_create_should_send_notification + Setting.notified_events << 'news_comment_added' + Watcher.create!(:watchable => @news, :user => @jsmith) + + assert_difference 'ActionMailer::Base.deliveries.size' do + Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment") + end + end def test_validate comment = Comment.new(:commented => @news) diff --git a/test/unit/lib/redmine/notifiable_test.rb b/test/unit/lib/redmine/notifiable_test.rb index fe02fbfc..7ca44920 100644 --- a/test/unit/lib/redmine/notifiable_test.rb +++ b/test/unit/lib/redmine/notifiable_test.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2008 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 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 @@ -22,9 +22,9 @@ class Redmine::NotifiableTest < ActiveSupport::TestCase end def test_all - assert_equal 11, Redmine::Notifiable.all.length + assert_equal 12, Redmine::Notifiable.all.length - %w(issue_added issue_updated issue_note_added issue_status_updated issue_priority_updated news_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_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/mailer_test.rb b/test/unit/mailer_test.rb index ae7c06d3..36ed4fe9 100644 --- a/test/unit/mailer_test.rb +++ b/test/unit/mailer_test.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 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 @@ -20,7 +20,7 @@ require File.expand_path('../../test_helper', __FILE__) class MailerTest < ActiveSupport::TestCase include Redmine::I18n include ActionController::Assertions::SelectorAssertions - fixtures :projects, :enabled_modules, :issues, :users, :members, :member_roles, :roles, :documents, :attachments, :news, :tokens, :journals, :journal_details, :changesets, :trackers, :issue_statuses, :enumerations, :messages, :boards, :repositories + fixtures :all def setup ActionMailer::Base.deliveries.clear @@ -295,6 +295,14 @@ class MailerTest < ActiveSupport::TestCase end end + def test_news_comment_added + comment = Comment.find(2) + valid_languages.each do |lang| + Setting.default_language = lang.to_s + assert Mailer.deliver_news_comment_added(comment) + end + end + def test_message_posted message = Message.find(:first) recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author} From dac912b379e12d3eedbe497cb26b0f60b26e6f83 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 4 Mar 2011 14:43:53 +0000 Subject: [PATCH 165/440] Fixed: Email notifications are sent to watchers even if 'No events' setting is chosen (#7763). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5004 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/watcher_test.rb | 10 +++++----- .../plugins/acts_as_watchable/lib/acts_as_watchable.rb | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/unit/watcher_test.rb b/test/unit/watcher_test.rb index 48c30313..86d96b2c 100644 --- a/test/unit/watcher_test.rb +++ b/test/unit/watcher_test.rb @@ -60,15 +60,15 @@ class WatcherTest < ActiveSupport::TestCase assert @issue.watcher_recipients.empty? assert @issue.add_watcher(@user) - @user.mail_notification = true - @user.save + @user.mail_notification = 'all' + @user.save! @issue.reload assert @issue.watcher_recipients.include?(@user.mail) - @user.mail_notification = false - @user.save + @user.mail_notification = 'none' + @user.save! @issue.reload - assert @issue.watcher_recipients.include?(@user.mail) + assert !@issue.watcher_recipients.include?(@user.mail) end def test_unwatch diff --git a/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb b/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb index e026a6dd..61196d9a 100644 --- a/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb +++ b/vendor/plugins/acts_as_watchable/lib/acts_as_watchable.rb @@ -58,7 +58,8 @@ module Redmine # Returns an array of watchers' email addresses def watcher_recipients notified = watcher_users.active - + notified.reject! {|user| user.mail_notification == 'none'} + if respond_to?(:visible?) notified.reject! {|user| !visible?(user)} end From 25ce0e6cd2fe9a04e1daf8ca35d365b066ca9c15 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 4 Mar 2011 14:52:47 +0000 Subject: [PATCH 166/440] Extends custom field possible values textarea. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5005 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/custom_fields/_form.rhtml | 1 - public/stylesheets/application.css | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/custom_fields/_form.rhtml b/app/views/custom_fields/_form.rhtml index a71df87a..f2be4292 100644 --- a/app/views/custom_fields/_form.rhtml +++ b/app/views/custom_fields/_form.rhtml @@ -61,7 +61,6 @@ function toggle_custom_field_format() { <%= f.text_field :max_length, :size => 5, :no_label => true %>
    (<%=l(:text_min_max_length_info)%>)

    <%= f.text_field :regexp, :size => 50 %>
    (<%=l(:text_regexp_info)%>)

    <%= f.text_area :possible_values, :value => @custom_field.possible_values.to_a.join("\n"), - :cols => 20, :rows => 15 %>
    <%= l(:text_custom_field_possible_values_info) %>

    <%= @custom_field.field_format == 'bool' ? f.check_box(:default_value) : f.text_field(:default_value) %>

    diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index d44ae546..bad96fc7 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -370,6 +370,8 @@ ul.properties li span {font-style:italic;} #workflow_copy_form select { width: 200px; } +textarea#custom_field_possible_values {width: 99%} + .pagination {font-size: 90%} p.pagination {margin-top:8px;} From 19083725ff07c5333980f394f8c445fd0b0197d6 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 4 Mar 2011 14:55:33 +0000 Subject: [PATCH 167/440] Removes duplicate DOM id in custom field form. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5006 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/custom_fields/_form.rhtml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/views/custom_fields/_form.rhtml b/app/views/custom_fields/_form.rhtml index f2be4292..d34c756d 100644 --- a/app/views/custom_fields/_form.rhtml +++ b/app/views/custom_fields/_form.rhtml @@ -60,9 +60,10 @@ function toggle_custom_field_format() { <%= f.text_field :min_length, :size => 5, :no_label => true %> - <%= f.text_field :max_length, :size => 5, :no_label => true %>
    (<%=l(:text_min_max_length_info)%>)

    <%= f.text_field :regexp, :size => 50 %>
    (<%=l(:text_regexp_info)%>)

    -

    <%= f.text_area :possible_values, :value => @custom_field.possible_values.to_a.join("\n"), - :rows => 15 %> -
    <%= l(:text_custom_field_possible_values_info) %>

    +

    + <%= f.text_area :possible_values, :value => @custom_field.possible_values.to_a.join("\n"), :rows => 15 %> +
    <%= l(:text_custom_field_possible_values_info) %> +

    <%= @custom_field.field_format == 'bool' ? f.check_box(:default_value) : f.text_field(:default_value) %>

    <%= call_hook(:view_custom_fields_form_upper_box, :custom_field => @custom_field, :form => f) %>
    From 52397646b2d79a6a6c42a64a57eec46a754286c9 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 4 Mar 2011 15:14:24 +0000 Subject: [PATCH 168/440] Fixed: Login page should not show projects link and search box if authentication is required (#3715). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5007 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/layouts/base.rhtml | 4 +++- test/integration/layout_test.rb | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/base.rhtml b/app/views/layouts/base.rhtml index 5e9d6399..a169116c 100644 --- a/app/views/layouts/base.rhtml +++ b/app/views/layouts/base.rhtml @@ -29,10 +29,11 @@ <%= render_menu :account_menu -%>
    <%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}", :id => 'loggedas') if User.current.logged? %> - <%= render_menu :top_menu -%> + <%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%>
    -<% users = User.active.find(:all, :limit => 100) - @group.users %> +<% users = User.active.not_in_group(@group).all(:limit => 100) %> <% if users.any? %> <% remote_form_for(:group, @group, :url => {:controller => 'groups', :action => 'add_users', :id => @group}, :method => :post) do |f| %>
    <%=l(:label_user_new)%> diff --git a/test/functional/groups_controller_test.rb b/test/functional/groups_controller_test.rb index a1a164b0..f45dfc45 100644 --- a/test/functional/groups_controller_test.rb +++ b/test/functional/groups_controller_test.rb @@ -104,4 +104,13 @@ class GroupsControllerTest < ActionController::TestCase post :destroy_membership, :id => 10, :membership_id => 6 end end + + def test_autocomplete_for_user + get :autocomplete_for_user, :id => 10, :q => 'mis' + assert_response :success + users = assigns(:users) + assert_not_nil users + assert users.any? + assert !users.include?(Group.find(10).users.first) + end end From cfbe69ab598a56c87420f9d7a70bfc37b172ab9d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 1 Apr 2011 18:42:41 +0000 Subject: [PATCH 421/440] Fixed: deleting a parent issue may lead to a stale object error (#7920). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5285 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/issue_nested_set_test.rb | 10 ++++++++++ .../awesome_nested_set/lib/awesome_nested_set.rb | 3 +++ 2 files changed, 13 insertions(+) diff --git a/test/unit/issue_nested_set_test.rb b/test/unit/issue_nested_set_test.rb index cf61cfde..46f4dc4d 100644 --- a/test/unit/issue_nested_set_test.rb +++ b/test/unit/issue_nested_set_test.rb @@ -223,6 +223,16 @@ class IssueNestedSetTest < ActiveSupport::TestCase assert_equal [issue1.id, 2, 3], [issue4.root_id, issue4.lft, issue4.rgt] end + def test_destroy_parent_issue_updated_during_children_destroy + parent = create_issue! + create_issue!(:start_date => Date.today, :parent_issue_id => parent.id) + create_issue!(:start_date => 2.days.from_now, :parent_issue_id => parent.id) + + assert_difference 'Issue.count', -3 do + Issue.find(parent.id).destroy + end + end + def test_destroy_child_issue_with_children root = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'root') child = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => root.id) diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb index fc5278d6..b2ebd669 100644 --- a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb +++ b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb @@ -466,6 +466,9 @@ module CollectiveIdea #:nodoc: ["#{quoted_right_column_name} >= ?", right] ) end + + # Reload is needed because children may have updated their parent (self) during deletion. + reload end # reload left, right, and parent From e6659501de3ce6fc2df095fbcd8b752b2102b7d9 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 1 Apr 2011 18:58:29 +0000 Subject: [PATCH 422/440] Limits nested set overhead when destroying an issue without children. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5286 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb index b2ebd669..b1e5ae1e 100644 --- a/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb +++ b/vendor/plugins/awesome_nested_set/lib/awesome_nested_set.rb @@ -444,11 +444,12 @@ module CollectiveIdea #:nodoc: # Prunes a branch off of the tree, shifting all of the elements on the right # back to the left so the counts still work. def prune_from_tree - return if right.nil? || left.nil? || !self.class.exists?(id) + return if right.nil? || left.nil? || leaf? || !self.class.exists?(id) delete_method = acts_as_nested_set_options[:dependent] == :destroy ? :destroy_all : :delete_all + # TODO: should destroy children (not descendants) when deleted_method is :destroy_all self.class.base_class.transaction do reload_nested_set nested_set_scope.send(delete_method, From 2431d830b10650bc6b30ab23602fe24a25ac8871 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 1 Apr 2011 19:04:26 +0000 Subject: [PATCH 423/440] No PUT request to get previous/next month. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5287 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/calendars_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/calendars_helper.rb b/app/helpers/calendars_helper.rb index 08e665dc..6953968c 100644 --- a/app/helpers/calendars_helper.rb +++ b/app/helpers/calendars_helper.rb @@ -37,7 +37,7 @@ module CalendarsHelper link_target = calendar_path(:year => year, :month => month, :project_id => project_id) link_to_remote(link_name, - {:update => "content", :url => link_target, :method => :put}, + {:update => "content", :url => link_target, :method => :get}, {:href => link_target}) end From ed867c4a7f970b982d46510145f5383303f53810 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 1 Apr 2011 19:32:07 +0000 Subject: [PATCH 424/440] Adds an index on users.type for faster retrieval of groups. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5288 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- db/migrate/20110401192910_add_index_to_users_type.rb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 db/migrate/20110401192910_add_index_to_users_type.rb diff --git a/db/migrate/20110401192910_add_index_to_users_type.rb b/db/migrate/20110401192910_add_index_to_users_type.rb new file mode 100644 index 00000000..b9f50112 --- /dev/null +++ b/db/migrate/20110401192910_add_index_to_users_type.rb @@ -0,0 +1,9 @@ +class AddIndexToUsersType < ActiveRecord::Migration + def self.up + add_index :users, :type + end + + def self.down + remove_index :users, :type + end +end From 6485f15bb912986fad13b09d102948f1a65324f8 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 2 Apr 2011 08:01:29 +0000 Subject: [PATCH 425/440] PDF: fix the problem that TCPDF built-in font breaks in the Windows (#61). This problem occurs because the EOF character string is included in the built-in font. Contributed by Jun NAITOH. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5290 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- vendor/plugins/rfpdf/lib/tcpdf.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/plugins/rfpdf/lib/tcpdf.rb b/vendor/plugins/rfpdf/lib/tcpdf.rb index da7d556f..1e444305 100755 --- a/vendor/plugins/rfpdf/lib/tcpdf.rb +++ b/vendor/plugins/rfpdf/lib/tcpdf.rb @@ -3063,7 +3063,7 @@ class TCPDF out('/Filter /FlateDecode'); end out('>>'); - open(ctgfile) do |f| + open(ctgfile, "rb") do |f| putstream(f.read()) end out('endobj'); From 7f0a29f7c2948cfc651bb3782c39a217650868f4 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 2 Apr 2011 08:01:47 +0000 Subject: [PATCH 426/440] PDF: set enable to use TCPDF UTF-8 on Windows except CJK and Thai (#61). Contributed by Jun NAITOH. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5291 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/export/pdf.rb | 6 ++---- lib/redmine/helpers/gantt.rb | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/redmine/export/pdf.rb b/lib/redmine/export/pdf.rb index d6f247ec..ccfd3421 100644 --- a/lib/redmine/export/pdf.rb +++ b/lib/redmine/export/pdf.rb @@ -179,8 +179,7 @@ module Redmine # Returns a PDF string of a list of issues def issues_to_pdf(issues, project, query) - if Redmine::Platform.mswin? || - ( current_language.to_s.downcase == 'ko' || + if ( current_language.to_s.downcase == 'ko' || current_language.to_s.downcase == 'ja' || current_language.to_s.downcase == 'zh' || current_language.to_s.downcase == 'zh-tw' || @@ -259,8 +258,7 @@ module Redmine # Returns a PDF string of a single issue def issue_to_pdf(issue) - if Redmine::Platform.mswin? || - ( current_language.to_s.downcase == 'ko' || + if ( current_language.to_s.downcase == 'ko' || current_language.to_s.downcase == 'ja' || current_language.to_s.downcase == 'zh' || current_language.to_s.downcase == 'zh-tw' || diff --git a/lib/redmine/helpers/gantt.rb b/lib/redmine/helpers/gantt.rb index bc0fafe4..6b891999 100644 --- a/lib/redmine/helpers/gantt.rb +++ b/lib/redmine/helpers/gantt.rb @@ -511,8 +511,7 @@ module Redmine end if Object.const_defined?(:Magick) def to_pdf - if Redmine::Platform.mswin? || - ( current_language.to_s.downcase == 'ko' || + if ( current_language.to_s.downcase == 'ko' || current_language.to_s.downcase == 'ja' || current_language.to_s.downcase == 'zh' || current_language.to_s.downcase == 'zh-tw' || From 3374130e608e15a89dfd031d3cfbfee79110604d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sat, 2 Apr 2011 10:18:05 +0000 Subject: [PATCH 427/440] Skip a few count(*) SQL queries on the issue list. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5292 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/query.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/models/query.rb b/app/models/query.rb index 0ef56c69..2249c37e 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -216,14 +216,19 @@ class Query < ActiveRecord::Base if project # project specific filters - unless @project.issue_categories.empty? - @available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } } + categories = @project.issue_categories.all + unless categories.empty? + @available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => categories.collect{|s| [s.name, s.id.to_s] } } end - unless @project.shared_versions.empty? - @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.shared_versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } } + versions = @project.shared_versions.all + unless versions.empty? + @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } } end - unless @project.descendants.active.empty? - @available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => @project.descendants.visible.collect{|s| [s.name, s.id.to_s] } } + unless @project.leaf? + subprojects = @project.descendants.visible.all + unless subprojects.empty? + @available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => subprojects.collect{|s| [s.name, s.id.to_s] } } + end end add_custom_fields_filters(@project.all_issue_custom_fields) else From 1d0b4dcdcc8906855288b6283d79316bbb9247e8 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sat, 2 Apr 2011 11:31:33 +0000 Subject: [PATCH 428/440] Do not load projects association in #rolled_up_trackers. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5293 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 9a7d8722..33078dd7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -353,7 +353,7 @@ class Project < ActiveRecord::Base # Returns an array of the trackers used by the project and its active sub projects def rolled_up_trackers @rolled_up_trackers ||= - Tracker.find(:all, :include => :projects, + Tracker.find(:all, :joins => :projects, :select => "DISTINCT #{Tracker.table_name}.*", :conditions => ["#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status = #{STATUS_ACTIVE}", lft, rgt], :order => "#{Tracker.table_name}.position") From 1cab1bd51e0ddca225dec68b5c2b34f163ee4dd9 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sat, 2 Apr 2011 11:46:20 +0000 Subject: [PATCH 429/440] Skip a count(*) SQL query. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5294 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f80cbbf2..ea2ddd13 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -143,7 +143,7 @@ class ProjectsController < ApplicationController end @users_by_role = @project.users_by_role - @subprojects = @project.children.visible + @subprojects = @project.children.visible.all @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") @trackers = @project.rolled_up_trackers From 73c5191196a2ce86e305dc0977e0bd6552526632 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sun, 3 Apr 2011 02:12:09 +0000 Subject: [PATCH 430/440] PDF: fix width calculation of multi byte character in Simplified and Traditional Chinese (#61). Contributed by Jun NAITOH. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5295 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- vendor/plugins/rfpdf/lib/fpdf/chinese.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/plugins/rfpdf/lib/fpdf/chinese.rb b/vendor/plugins/rfpdf/lib/fpdf/chinese.rb index e072e515..94f8ee49 100644 --- a/vendor/plugins/rfpdf/lib/fpdf/chinese.rb +++ b/vendor/plugins/rfpdf/lib/fpdf/chinese.rb @@ -210,7 +210,7 @@ module PDF_Chinese #Automatic line break if(sep==-1 or i==j) if(i==j) - i+=ascii ? 1 : 3 + i+=ascii ? 1 : 2 end Cell(w,h,s[j,i-j],b,2,align,fill) else @@ -225,7 +225,7 @@ module PDF_Chinese b=b2 end else - i+=ascii ? 1 : 3 + i+=ascii ? 1 : 2 end end #Last chunk @@ -294,7 +294,7 @@ module PDF_Chinese next end if(i==j) - i+=ascii ? 1 : 3 + i+=ascii ? 1 : 2 end Cell(w,h,s[j,i-j],0,2,'',0,link) else @@ -311,7 +311,7 @@ module PDF_Chinese end nl+=1 else - i+=ascii ? 1 : 3 + i+=ascii ? 1 : 2 end end #Last chunk From 966a7a9c3462f8b0d5e7126a37b5fb9276da7bc6 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sun, 3 Apr 2011 02:47:06 +0000 Subject: [PATCH 431/440] PDF: code clean up lib/redmine/export/pdf.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5296 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/export/pdf.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/redmine/export/pdf.rb b/lib/redmine/export/pdf.rb index ccfd3421..baf553ca 100644 --- a/lib/redmine/export/pdf.rb +++ b/lib/redmine/export/pdf.rb @@ -132,7 +132,7 @@ module Redmine end || '' super(txt) end - + def textstring(s) # Format a text string if s =~ /^ Date: Sun, 3 Apr 2011 11:55:24 +0000 Subject: [PATCH 432/440] Changed timelogs filters to use non-AJAX requests (#1965). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5297 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/time_entry_reports/report.rhtml | 9 +++----- app/views/timelog/_date_range.rhtml | 10 +++------ app/views/timelog/index.html.erb | 6 +---- config/routes.rb | 7 +++--- .../time_entry_reports_controller_test.rb | 10 +++++++-- test/functional/timelog_controller_test.rb | 22 +++++++++++++++---- 6 files changed, 37 insertions(+), 27 deletions(-) diff --git a/app/views/time_entry_reports/report.rhtml b/app/views/time_entry_reports/report.rhtml index 5ae9d655..18e782cc 100644 --- a/app/views/time_entry_reports/report.rhtml +++ b/app/views/time_entry_reports/report.rhtml @@ -6,7 +6,7 @@

    <%= l(:label_spent_time) %>

    -<% form_remote_tag(:url => {}, :html => {:method => :get, :id => 'query_form'}, :method => :get, :update => 'content') do %> +<% form_tag({:controller => 'time_entry_reports', :action => 'report', :project_id => @project, :issue_id => @issue}, :method => :get, :id => 'query_form') do %> <% @criterias.each do |criteria| %> <%= hidden_field_tag 'criterias[]', criteria, :id => nil %> <% end %> @@ -22,14 +22,11 @@ :onchange => "this.form.onsubmit();" %> <%= l(:button_add) %>: <%= select_tag('criterias[]', options_for_select([[]] + (@available_criterias.keys - @criterias).collect{|k| [l_or_humanize(@available_criterias[k][:label]), k]}), - :onchange => "this.form.onsubmit();", + :onchange => "this.form.submit();", :style => 'width: 200px', :id => nil, :disabled => (@criterias.length >= 3)) %> - <%= link_to_remote l(:button_clear), {:url => {:project_id => @project, :period_type => params[:period_type], :period => params[:period], :from => @from, :to => @to, :columns => @columns}, - :method => :get, - :update => 'content' - }, :class => 'icon icon-reload' %>

    + <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue, :period_type => params[:period_type], :period => params[:period], :from => @from, :to => @to, :columns => @columns}, :class => 'icon icon-reload' %>

    <% end %> <% unless @criterias.empty? %> diff --git a/app/views/timelog/_date_range.rhtml b/app/views/timelog/_date_range.rhtml index 727de25e..42ea53b7 100644 --- a/app/views/timelog/_date_range.rhtml +++ b/app/views/timelog/_date_range.rhtml @@ -4,7 +4,7 @@

    <%= radio_button_tag 'period_type', '1', !@free_period %> <%= select_tag 'period', options_for_period_select(params[:period]), - :onchange => 'this.form.onsubmit();', + :onchange => 'this.form.submit();', :onfocus => '$("period_type_1").checked = true;' %>

    @@ -17,12 +17,8 @@

    - <%= link_to_remote l(:button_apply), - { :url => { }, - :update => "content", - :with => "Form.serialize('query_form')", - :method => :get - }, :class => 'icon icon-checked' %> + <%= link_to_function l(:button_apply), '$("query_form").submit()', :class => 'icon icon-checked' %> + <%= link_to l(:button_clear), {:controller => controller_name, :action => action_name, :project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>

    diff --git a/app/views/timelog/index.html.erb b/app/views/timelog/index.html.erb index 737476f3..d943d430 100644 --- a/app/views/timelog/index.html.erb +++ b/app/views/timelog/index.html.erb @@ -6,11 +6,7 @@

    <%= l(:label_spent_time) %>

    -<% form_remote_tag( :url => {}, :html => {:method => :get, :id => 'query_form'}, :method => :get, :update => 'content' ) do %> -<%# TOOD: remove the project_id and issue_id hidden fields, that information is -already in the URI %> -<%= hidden_field_tag('project_id', params[:project_id]) if @project %> -<%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %> +<% form_tag({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}, :method => :get, :id => 'query_form') do %> <%= render :partial => 'date_range' %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 3b37b515..378fdb0b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,14 +14,15 @@ ActionController::Routing::Routes.draw do |map| map.connect 'roles/workflow/:id/:role_id/:tracker_id', :controller => 'roles', :action => 'workflow' map.connect 'help/:ctrl/:page', :controller => 'help' - map.connect 'projects/:project_id/time_entries/report', :controller => 'time_entry_reports', :action => 'report' map.with_options :controller => 'time_entry_reports', :action => 'report',:conditions => {:method => :get} do |time_report| + time_report.connect 'projects/:project_id/issues/:issue_id/time_entries/report' + time_report.connect 'projects/:project_id/issues/:issue_id/time_entries/report.:format' + time_report.connect 'projects/:project_id/time_entries/report' + time_report.connect 'projects/:project_id/time_entries/report.:format' time_report.connect 'time_entries/report' time_report.connect 'time_entries/report.:format' - time_report.connect 'projects/:project_id/time_entries/report.:format' end - # TODO: wasteful since this is also nested under issues, projects, and projects/issues map.resources :time_entries, :controller => 'timelog' map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post} diff --git a/test/functional/time_entry_reports_controller_test.rb b/test/functional/time_entry_reports_controller_test.rb index 70a3d1c7..b53eebd7 100644 --- a/test/functional/time_entry_reports_controller_test.rb +++ b/test/functional/time_entry_reports_controller_test.rb @@ -4,16 +4,20 @@ require File.expand_path('../../test_helper', __FILE__) class TimeEntryReportsControllerTest < ActionController::TestCase fixtures :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :time_entries, :users, :trackers, :enumerations, :issue_statuses, :custom_fields, :custom_values - def test_report_no_criteria - get :report, :project_id => 1 + def test_report_at_project_level + get :report, :project_id => 'ecookbook' assert_response :success assert_template 'report' + assert_tag :form, + :attributes => {:action => "/projects/ecookbook/time_entries/report", :id => 'query_form'} end def test_report_all_projects get :report assert_response :success assert_template 'report' + assert_tag :form, + :attributes => {:action => "/time_entries/report", :id => 'query_form'} end def test_report_all_projects_denied @@ -80,6 +84,8 @@ class TimeEntryReportsControllerTest < ActionController::TestCase assert_template 'report' assert_not_nil assigns(:total_hours) assert_equal "154.25", "%.2f" % assigns(:total_hours) + assert_tag :form, + :attributes => {:action => "/projects/ecookbook/issues/1/time_entries/report", :id => 'query_form'} end def test_report_custom_field_criteria diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb index 634363dd..669014d8 100644 --- a/test/functional/timelog_controller_test.rb +++ b/test/functional/timelog_controller_test.rb @@ -163,10 +163,12 @@ class TimelogControllerTest < ActionController::TestCase assert_template 'index' assert_not_nil assigns(:total_hours) assert_equal "162.90", "%.2f" % assigns(:total_hours) + assert_tag :form, + :attributes => {:action => "/time_entries", :id => 'query_form'} end def test_index_at_project_level - get :index, :project_id => 1 + get :index, :project_id => 'ecookbook' assert_response :success assert_template 'index' assert_not_nil assigns(:entries) @@ -178,10 +180,12 @@ class TimelogControllerTest < ActionController::TestCase # display all time by default assert_equal '2007-03-12'.to_date, assigns(:from) assert_equal '2007-04-22'.to_date, assigns(:to) + assert_tag :form, + :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'} end def test_index_at_project_level_with_date_range - get :index, :project_id => 1, :from => '2007-03-20', :to => '2007-04-30' + get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30' assert_response :success assert_template 'index' assert_not_nil assigns(:entries) @@ -190,24 +194,30 @@ class TimelogControllerTest < ActionController::TestCase assert_equal "12.90", "%.2f" % assigns(:total_hours) assert_equal '2007-03-20'.to_date, assigns(:from) assert_equal '2007-04-30'.to_date, assigns(:to) + assert_tag :form, + :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'} end def test_index_at_project_level_with_period - get :index, :project_id => 1, :period => '7_days' + get :index, :project_id => 'ecookbook', :period => '7_days' assert_response :success assert_template 'index' assert_not_nil assigns(:entries) assert_not_nil assigns(:total_hours) assert_equal Date.today - 7, assigns(:from) assert_equal Date.today, assigns(:to) + assert_tag :form, + :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'} end def test_index_one_day - get :index, :project_id => 1, :from => "2007-03-23", :to => "2007-03-23" + get :index, :project_id => 'ecookbook', :from => "2007-03-23", :to => "2007-03-23" assert_response :success assert_template 'index' assert_not_nil assigns(:total_hours) assert_equal "4.25", "%.2f" % assigns(:total_hours) + assert_tag :form, + :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'} end def test_index_at_issue_level @@ -221,6 +231,10 @@ class TimelogControllerTest < ActionController::TestCase # display all time based on what's been logged assert_equal '2007-03-12'.to_date, assigns(:from) assert_equal '2007-04-22'.to_date, assigns(:to) + # TODO: remove /projects/:project_id/issues/:issue_id/time_entries routes + # to use /issues/:issue_id/time_entries + assert_tag :form, + :attributes => {:action => "/projects/ecookbook/issues/1/time_entries", :id => 'query_form'} end def test_index_atom_feed From 82b638f727eb18c844c3323b8c466698ee15832e Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Apr 2011 12:02:10 +0000 Subject: [PATCH 433/440] Removed hidden project_id and issue_id parameters. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5298 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/time_entry_reports/report.rhtml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/views/time_entry_reports/report.rhtml b/app/views/time_entry_reports/report.rhtml index 18e782cc..de2d1093 100644 --- a/app/views/time_entry_reports/report.rhtml +++ b/app/views/time_entry_reports/report.rhtml @@ -10,9 +10,6 @@ <% @criterias.each do |criteria| %> <%= hidden_field_tag 'criterias[]', criteria, :id => nil %> <% end %> - <%# TODO: get rid of the project_id field, that should already be in the URL %> - <%= hidden_field_tag('project_id', params[:project_id]) if @project %> - <%= hidden_field_tag('issue_id', params[:issue_id]) if @issue %> <%= render :partial => 'timelog/date_range' %>

    <%= l(:label_details) %>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'], From 0c0763ad4b87a1bdd13b7b8522e7313a3a824b4d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Apr 2011 12:02:56 +0000 Subject: [PATCH 434/440] Disable unused fields when switching the period type. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5299 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/timelog/_date_range.rhtml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/views/timelog/_date_range.rhtml b/app/views/timelog/_date_range.rhtml index 42ea53b7..e916bc18 100644 --- a/app/views/timelog/_date_range.rhtml +++ b/app/views/timelog/_date_range.rhtml @@ -2,16 +2,17 @@ <%= l(:label_date_range) %>

    -<%= radio_button_tag 'period_type', '1', !@free_period %> +<%= radio_button_tag 'period_type', '1', !@free_period, :onclick => 'Form.Element.disable("from");Form.Element.disable("to");Form.Element.enable("period");' %> <%= select_tag 'period', options_for_period_select(params[:period]), :onchange => 'this.form.submit();', - :onfocus => '$("period_type_1").checked = true;' %> + :onfocus => '$("period_type_1").checked = true;', + :disabled => @free_period %>

    -<%= radio_button_tag 'period_type', '2', @free_period %> +<%= radio_button_tag 'period_type', '2', @free_period, :onclick => 'Form.Element.enable("from");Form.Element.enable("to");Form.Element.disable("period");' %> -<%= l(:label_date_from_to, :start => (text_field_tag('from', @from, :size => 10) + calendar_for('from')), - :end => (text_field_tag('to', @to, :size => 10) + calendar_for('to'))) %> +<%= l(:label_date_from_to, :start => (text_field_tag('from', @from, :size => 10, :disabled => !@free_period) + calendar_for('from')), + :end => (text_field_tag('to', @to, :size => 10, :disabled => !@free_period) + calendar_for('to'))) %>

    From 844c0d97aad079806577a348aef4898daf9c5b50 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Apr 2011 12:33:27 +0000 Subject: [PATCH 435/440] Removed the changeset-changes class to the commit logs on the issue view (#8038). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5300 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/issues/_changesets.rhtml | 2 +- public/stylesheets/rtl.css | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/issues/_changesets.rhtml b/app/views/issues/_changesets.rhtml index d5a29289..76e9a281 100644 --- a/app/views/issues/_changesets.rhtml +++ b/app/views/issues/_changesets.rhtml @@ -3,7 +3,7 @@

    <%= link_to_revision(changeset, changeset.project, :text => "#{l(:label_revision)} #{changeset.format_identifier}") %>
    <%= authoring(changeset.committed_on, changeset.author) %>

    -
    +
    <%= textilizable(changeset, :comments) %>
    diff --git a/public/stylesheets/rtl.css b/public/stylesheets/rtl.css index 5dfe320b..ea6574bc 100644 --- a/public/stylesheets/rtl.css +++ b/public/stylesheets/rtl.css @@ -56,6 +56,7 @@ table.list td.buttons a { padding-right: 20px; } .changeset-changes { direction: ltr; padding-left: 2em } .changesets { direction: ltr; } div#issue-changesets { float: left; margin-right: 1em; margin-left: 0 } +div#issue-changesets div.wiki { direction: ltr; padding-left: 2em } #activity dt, .journal { clear: right; } .journal-link { float: left; } div.wiki pre { direction: ltr; } From 07cf681d61f89b372eaff6702acfb3738136e78c Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Apr 2011 14:01:32 +0000 Subject: [PATCH 436/440] Makes all pagination-like links use #link_to_content_update (#5138). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5301 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/application_helper.rb | 16 ++++++---------- app/helpers/calendars_helper.rb | 10 +--------- app/helpers/gantt_helper.rb | 14 ++++++-------- app/helpers/sort_helper.rb | 5 +---- app/views/activities/index.html.erb | 14 ++++++-------- app/views/gantts/show.html.erb | 4 ++-- app/views/search/index.rhtml | 12 ++++-------- 7 files changed, 26 insertions(+), 49 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 68291797..90439b7d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -340,15 +340,15 @@ module ApplicationHelper html = '' if paginator.current.previous - html << link_to_remote_content_update('« ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' ' + html << link_to_content_update('« ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' ' end html << (pagination_links_each(paginator, options) do |n| - link_to_remote_content_update(n.to_s, url_param.merge(page_param => n)) + link_to_content_update(n.to_s, url_param.merge(page_param => n)) end || '') if paginator.current.next - html << ' ' + link_to_remote_content_update((l(:label_next) + ' »'), url_param.merge(page_param => paginator.current.next)) + html << ' ' + link_to_content_update((l(:label_next) + ' »'), url_param.merge(page_param => paginator.current.next)) end unless count.nil? @@ -363,10 +363,7 @@ module ApplicationHelper def per_page_links(selected=nil) links = Setting.per_page_options_array.collect do |n| - n == selected ? n : link_to_remote(n, {:update => "content", - :url => params.merge(:per_page => n), - :method => :get}, - {:href => url_for(params.merge(:per_page => n))}) + n == selected ? n : link_to_content_update(n, params.merge(:per_page => n)) end links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil end @@ -944,11 +941,10 @@ module ApplicationHelper return self end - def link_to_remote_content_update(text, url_params) + def link_to_content_update(text, url_params = {}, html_options = {}) link_to_remote(text, {:url => url_params, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'}, - {:href => url_for(:params => url_params)} + {:href => url_for(:params => url_params)}.merge(html_options) ) end - end diff --git a/app/helpers/calendars_helper.rb b/app/helpers/calendars_helper.rb index 6953968c..82f3905e 100644 --- a/app/helpers/calendars_helper.rb +++ b/app/helpers/calendars_helper.rb @@ -32,14 +32,6 @@ module CalendarsHelper end def link_to_month(link_name, year, month, options={}) - project_id = options[:project].present? ? options[:project].to_param : nil - - link_target = calendar_path(:year => year, :month => month, :project_id => project_id) - - link_to_remote(link_name, - {:update => "content", :url => link_target, :method => :get}, - {:href => link_target}) - + link_to_content_update(link_name, params.merge(:year => year, :month => month)) end - end diff --git a/app/helpers/gantt_helper.rb b/app/helpers/gantt_helper.rb index aa743856..059a6457 100644 --- a/app/helpers/gantt_helper.rb +++ b/app/helpers/gantt_helper.rb @@ -21,20 +21,18 @@ module GanttHelper case in_or_out when :in if gantt.zoom < 4 - link_to_remote(l(:text_zoom_in), - {:url => gantt.params.merge(:zoom => (gantt.zoom+1)), :method => :get, :update => 'content'}, - {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom+1))), - :class => 'icon icon-zoom-in'}) + link_to_content_update l(:text_zoom_in), + params.merge(gantt.params.merge(:zoom => (gantt.zoom+1))), + :class => 'icon icon-zoom-in' else content_tag('span', l(:text_zoom_in), :class => 'icon icon-zoom-in') end when :out if gantt.zoom > 1 - link_to_remote(l(:text_zoom_out), - {:url => gantt.params.merge(:zoom => (gantt.zoom-1)), :method => :get, :update => 'content'}, - {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom-1))), - :class => 'icon icon-zoom-out'}) + link_to_content_update l(:text_zoom_out), + params.merge(gantt.params.merge(:zoom => (gantt.zoom-1))), + :class => 'icon icon-zoom-out' else content_tag('span', l(:text_zoom_out), :class => 'icon icon-zoom-out') end diff --git a/app/helpers/sort_helper.rb b/app/helpers/sort_helper.rb index c1a89db5..2dc24534 100644 --- a/app/helpers/sort_helper.rb +++ b/app/helpers/sort_helper.rb @@ -206,10 +206,7 @@ module SortHelper # Add project_id to url_options url_options = url_options.merge(:project_id => params[:project_id]) if params.has_key?(:project_id) - link_to_remote(caption, - {:update => "content", :url => url_options, :method => :get}, - {:href => url_for(url_options), - :class => css}) + link_to_content_update(caption, url_options, :class => css) end # Returns a table header tag with a sort link for the named column diff --git a/app/views/activities/index.html.erb b/app/views/activities/index.html.erb index 03cc8c68..a2748cc9 100644 --- a/app/views/activities/index.html.erb +++ b/app/views/activities/index.html.erb @@ -21,16 +21,14 @@ <%= content_tag('p', l(:label_no_data), :class => 'nodata') if @events_by_day.empty? %>
    -<%= link_to_remote(('« ' + l(:label_previous)), - {:update => "content", :url => params.merge(:from => @date_to - @days - 1), :method => :get, :complete => 'window.scrollTo(0,0)'}, - {:href => url_for(params.merge(:from => @date_to - @days - 1)), - :title => l(:label_date_from_to, :start => format_date(@date_to - 2*@days), :end => format_date(@date_to - @days - 1))}) %> +<%= link_to_content_update('« ' + l(:label_previous), + params.merge(:from => @date_to - @days - 1), + :title => l(:label_date_from_to, :start => format_date(@date_to - 2*@days), :end => format_date(@date_to - @days - 1))) %>
    -<%= link_to_remote((l(:label_next) + ' »'), - {:update => "content", :url => params.merge(:from => @date_to + @days - 1), :method => :get, :complete => 'window.scrollTo(0,0)'}, - {:href => url_for(params.merge(:from => @date_to + @days - 1)), - :title => l(:label_date_from_to, :start => format_date(@date_to), :end => format_date(@date_to + @days - 1))}) unless @date_to >= Date.today %> +<%= link_to_content_update(l(:label_next) + ' »', + params.merge(:from => @date_to + @days - 1), + :title => l(:label_date_from_to, :start => format_date(@date_to), :end => format_date(@date_to + @days - 1))) unless @date_to >= Date.today %>
      <% other_formats_links do |f| %> diff --git a/app/views/gantts/show.html.erb b/app/views/gantts/show.html.erb index 1e38647e..8007bbab 100644 --- a/app/views/gantts/show.html.erb +++ b/app/views/gantts/show.html.erb @@ -178,8 +178,8 @@ if Date.today >= @gantt.date_from and Date.today <= @gantt.date_to %> - - + +
    <%= link_to_remote ('« ' + l(:label_previous)), {:url => @gantt.params_previous, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'}, {:href => url_for(@gantt.params_previous)} %><%= link_to_remote (l(:label_next) + ' »'), {:url => @gantt.params_next, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'}, {:href => url_for(@gantt.params_next)} %><%= link_to_content_update('« ' + l(:label_previous), params.merge(@gantt.params_previous)) %><%= link_to_content_update(l(:label_next) + ' »', params.merge(@gantt.params_next)) %>
    diff --git a/app/views/search/index.rhtml b/app/views/search/index.rhtml index 348421d3..13ec567d 100644 --- a/app/views/search/index.rhtml +++ b/app/views/search/index.rhtml @@ -35,16 +35,12 @@

    <% if @pagination_previous_date %> -<%= link_to_remote ('« ' + l(:label_previous)), - {:update => :content, - :url => params.merge(:previous => 1, :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S")) - }, :href => url_for(params.merge(:previous => 1, :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))) %>  +<%= link_to_content_update('« ' + l(:label_previous), + params.merge(:previous => 1, :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))) %>  <% end %> <% if @pagination_next_date %> -<%= link_to_remote (l(:label_next) + ' »'), - {:update => :content, - :url => params.merge(:previous => nil, :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S")) - }, :href => url_for(params.merge(:previous => nil, :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))) %> +<%= link_to_content_update(l(:label_next) + ' »', + params.merge(:previous => nil, :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))) %> <% end %>

    From 1335548949efcc95f539dd7444664c9eb5269cbc Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Apr 2011 14:06:53 +0000 Subject: [PATCH 437/440] Changes pagination links to non-AJAX requests (#5138). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5302 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/application_helper.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 90439b7d..69d55f34 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -942,9 +942,6 @@ module ApplicationHelper end def link_to_content_update(text, url_params = {}, html_options = {}) - link_to_remote(text, - {:url => url_params, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'}, - {:href => url_for(:params => url_params)}.merge(html_options) - ) + link_to(text, url_params, html_options) end end From e78149f85cb886c02405b94ccd17c6c0a21ccdcc Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Apr 2011 14:09:22 +0000 Subject: [PATCH 438/440] Keep issue filter params on sort headers. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5303 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/sort_helper.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/helpers/sort_helper.rb b/app/helpers/sort_helper.rb index 2dc24534..a1808a05 100644 --- a/app/helpers/sort_helper.rb +++ b/app/helpers/sort_helper.rb @@ -200,8 +200,7 @@ module SortHelper caption = column.to_s.humanize unless caption sort_options = { :sort => @sort_criteria.add(column.to_s, order).to_param } - # don't reuse params if filters are present - url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options) + url_options = params.merge(sort_options) # Add project_id to url_options url_options = url_options.merge(:project_id => params[:project_id]) if params.has_key?(:project_id) From 42653cef3257469cdba56c73ca554fc15dcd7644 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 3 Apr 2011 14:31:32 +0000 Subject: [PATCH 439/440] Shorten query[column_names] param name. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5304 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/queries_controller.rb | 5 ++++- app/helpers/queries_helper.rb | 2 +- app/views/queries/_columns.rhtml | 2 +- test/functional/issues_controller_test.rb | 2 +- test/functional/queries_controller_test.rb | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb index e54c9bef..60f3b445 100644 --- a/app/controllers/queries_controller.rb +++ b/app/controllers/queries_controller.rb @@ -25,10 +25,11 @@ class QueriesController < ApplicationController @query.project = params[:query_is_for_all] ? nil : @project @query.user = User.current @query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin? - @query.column_names = nil if params[:default_columns] @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f] @query.group_by ||= params[:group_by] + @query.column_names = params[:c] if params[:c] + @query.column_names = nil if params[:default_columns] if request.post? && params[:confirm] && @query.save flash[:notice] = l(:notice_successful_create) @@ -45,6 +46,8 @@ class QueriesController < ApplicationController @query.attributes = params[:query] @query.project = nil if params[:query_is_for_all] @query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin? + @query.group_by ||= params[:group_by] + @query.column_names = params[:c] if params[:c] @query.column_names = nil if params[:default_columns] if @query.save diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb index b6dc697e..61a1846d 100644 --- a/app/helpers/queries_helper.rb +++ b/app/helpers/queries_helper.rb @@ -87,7 +87,7 @@ module QueriesHelper end end @query.group_by = params[:group_by] - @query.column_names = params[:query] && params[:query][:column_names] + @query.column_names = params[:c] || (params[:query] && params[:query][:column_names]) session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names} else @query = Query.find_by_id(session[:query][:id]) if session[:query][:id] diff --git a/app/views/queries/_columns.rhtml b/app/views/queries/_columns.rhtml index 91ee627b..f96d87b0 100644 --- a/app/views/queries/_columns.rhtml +++ b/app/views/queries/_columns.rhtml @@ -10,7 +10,7 @@ - <%= select_tag 'query[column_names][]', + <%= select_tag 'c[]', options_for_select(query.columns.collect {|column| [column.caption, column.name]}), :id => 'selected_columns', :multiple => true, :size => 10, :style => "width:150px" %> diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index da25ac06..d013b59e 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -248,7 +248,7 @@ class IssuesControllerTest < ActionController::TestCase def test_index_with_columns columns = ['tracker', 'subject', 'assigned_to'] - get :index, :set_filter => 1, :query => { 'column_names' => columns} + get :index, :set_filter => 1, :c => columns assert_response :success # query should use specified columns diff --git a/test/functional/queries_controller_test.rb b/test/functional/queries_controller_test.rb index 3ef897d6..ea3a7ada 100644 --- a/test/functional/queries_controller_test.rb +++ b/test/functional/queries_controller_test.rb @@ -101,7 +101,8 @@ class QueriesControllerTest < ActionController::TestCase :fields => ["status_id", "assigned_to_id"], :operators => {"assigned_to_id" => "=", "status_id" => "o"}, :values => { "assigned_to_id" => ["me"], "status_id" => ["1"]}, - :query => {"name" => "test_new_global_private_query", "is_public" => "1", "column_names" => ["", "tracker", "subject", "priority", "category"]} + :query => {"name" => "test_new_global_private_query", "is_public" => "1"}, + :c => ["", "tracker", "subject", "priority", "category"] q = Query.find_by_name('test_new_global_private_query') assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q From f06f846fcedc782637d1c9ec750c8ae34641e23e Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Sat, 16 Apr 2011 16:19:31 -0700 Subject: [PATCH 440/440] Locales update post-merge --- config/locales/bg.yml | 5 +++++ config/locales/bs.yml | 9 +++++++++ config/locales/ca.yml | 9 +++++++++ config/locales/cs.yml | 9 +++++++++ config/locales/da.yml | 9 +++++++++ config/locales/de.yml | 9 +++++++++ config/locales/el.yml | 9 +++++++++ config/locales/en-GB.yml | 2 ++ config/locales/es.yml | 9 +++++++++ config/locales/eu.yml | 9 +++++++++ config/locales/fa.yml | 16 ++++++++++++++++ config/locales/fi.yml | 9 +++++++++ config/locales/fr.yml | 1 + config/locales/gl.yml | 9 +++++++++ config/locales/he.yml | 9 +++++++++ config/locales/hr.yml | 9 +++++++++ config/locales/hu.yml | 9 +++++++++ config/locales/id.yml | 9 +++++++++ config/locales/it.yml | 9 +++++++++ config/locales/ja.yml | 3 +++ config/locales/ko.yml | 9 +++++++++ config/locales/lt.yml | 9 +++++++++ config/locales/lv.yml | 9 +++++++++ config/locales/mk.yml | 9 +++++++++ config/locales/mn.yml | 9 +++++++++ config/locales/nl.yml | 10 ++++++++++ config/locales/no.yml | 9 +++++++++ config/locales/pl.yml | 9 +++++++++ config/locales/pt-BR.yml | 9 +++++++++ config/locales/pt.yml | 9 +++++++++ config/locales/ro.yml | 9 +++++++++ config/locales/ru.yml | 9 +++++++++ config/locales/sk.yml | 9 +++++++++ config/locales/sl.yml | 9 +++++++++ config/locales/sr-YU.yml | 9 +++++++++ config/locales/sr.yml | 9 +++++++++ config/locales/sv.yml | 6 ++++++ config/locales/th.yml | 9 +++++++++ config/locales/tr.yml | 9 +++++++++ config/locales/uk.yml | 9 +++++++++ config/locales/vi.yml | 9 +++++++++ config/locales/zh-TW.yml | 6 ++++++ config/locales/zh.yml | 9 +++++++++ 43 files changed, 364 insertions(+) diff --git a/config/locales/bg.yml b/config/locales/bg.yml index e36d07fc..a836fd71 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -950,3 +950,8 @@ bg: label_cvs_path: CVSROOT label_git_path: Path to .git directory label_mercurial_path: Root directory + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date diff --git a/config/locales/bs.yml b/config/locales/bs.yml index 04d4c99f..ba4ff7e6 100644 --- a/config/locales/bs.yml +++ b/config/locales/bs.yml @@ -960,3 +960,12 @@ bs: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 62e69ace..475a64d7 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -949,3 +949,12 @@ ca: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 0b3110a0..ca50d4a8 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1170,3 +1170,12 @@ cs: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/da.yml b/config/locales/da.yml index fad0592f..bc86533e 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -962,3 +962,12 @@ da: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/de.yml b/config/locales/de.yml index d62eb2ce..5567b6fe 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -963,3 +963,12 @@ de: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/el.yml b/config/locales/el.yml index 98f7dae3..4b5d6ffa 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -946,3 +946,12 @@ el: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 8255a61a..5d5ca653 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -957,3 +957,5 @@ en-GB: label_cvs_path: CVSROOT label_git_path: Path to .git directory label_mercurial_path: Root directory + 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 diff --git a/config/locales/es.yml b/config/locales/es.yml index b6b6ed92..6ad49263 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -983,3 +983,12 @@ es: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/eu.yml b/config/locales/eu.yml index 425a6070..3a5085c2 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -950,3 +950,12 @@ eu: notice_gantt_chart_truncated: Grafikoa moztu da bistara daitekeen elementuen kopuru maximoa gainditu delako (%{max}) setting_gantt_items_limit: "Gantt grafikoan bistara daitekeen elementu kopuru maximoa" label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 03186b77..19bcdb78 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -942,3 +942,19 @@ fa: text_tip_issue_end_day: issue ending this day text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. label_my_queries: My custom queries + label_cvs_module: Module + label_filesystem_path: Root directory + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + label_darcs_path: Root directory + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + label_news_comment_added: Comment added to a news + label_bazaar_path: Root directory + label_cvs_path: CVSROOT + label_git_path: Path to .git directory + default_role_anonymous: Anonymous + text_powered_by: Powered by %{link} + default_role_non_member: Non member + label_mercurial_path: Root directory diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 948aaae2..d2bf6b3c 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -967,3 +967,12 @@ fi: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/fr.yml b/config/locales/fr.yml index e038fc74..f21fcc2f 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -972,3 +972,4 @@ fr: label_cvs_path: CVSROOT label_git_path: Path to .git directory label_mercurial_path: Root directory + field_effective_date: Due date diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 6e98cb7f..8f6b9bb4 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -958,3 +958,12 @@ gl: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/he.yml b/config/locales/he.yml index 767d4754..e45a7e0a 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -951,3 +951,12 @@ he: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 93ae02af..4e086faa 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -953,3 +953,12 @@ hr: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 9f124a6d..c951c5da 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -965,3 +965,12 @@ label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/id.yml b/config/locales/id.yml index ba2d27e3..747ced09 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -954,3 +954,12 @@ id: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/it.yml b/config/locales/it.yml index 45e693e9..7d66fa0e 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -947,3 +947,12 @@ it: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 66013b3c..b05c5164 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -974,3 +974,6 @@ ja: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + 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 diff --git a/config/locales/ko.yml b/config/locales/ko.yml index bd6a96cf..3f2401f4 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -998,3 +998,12 @@ ko: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/lt.yml b/config/locales/lt.yml index bea93e63..d310fb7b 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -1006,3 +1006,12 @@ lt: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 51e95ea0..0640637e 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -941,3 +941,12 @@ lv: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/mk.yml b/config/locales/mk.yml index 970608a8..e46c7c88 100644 --- a/config/locales/mk.yml +++ b/config/locales/mk.yml @@ -946,3 +946,12 @@ mk: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/mn.yml b/config/locales/mn.yml index 08dd597e..31004e0c 100644 --- a/config/locales/mn.yml +++ b/config/locales/mn.yml @@ -947,3 +947,12 @@ mn: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/nl.yml b/config/locales/nl.yml index ea7332ec..9f215c3e 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -927,3 +927,13 @@ nl: 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 + label_cvs_module: Module + label_filesystem_path: Root directory + label_darcs_path: Root directory + text_journal_changed_no_detail: "%{label} updated" + field_effective_date: Due date + label_bazaar_path: Root directory + label_cvs_path: CVSROOT + label_git_path: Path to .git directory + text_powered_by: Powered by %{link} + label_mercurial_path: Root directory diff --git a/config/locales/no.yml b/config/locales/no.yml index 79a2a609..73c42c61 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -933,3 +933,12 @@ label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 66f35161..31724818 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -963,3 +963,12 @@ pl: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index d11f3cd0..aa438e75 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -969,3 +969,12 @@ pt-BR: 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 + label_cvs_module: Module + label_filesystem_path: Root directory + label_darcs_path: Root directory + field_effective_date: Due date + label_bazaar_path: Root directory + label_cvs_path: CVSROOT + label_git_path: Path to .git directory + text_powered_by: Powered by %{link} + label_mercurial_path: Root directory diff --git a/config/locales/pt.yml b/config/locales/pt.yml index fbc0c365..787a3a94 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -950,3 +950,12 @@ pt: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/ro.yml b/config/locales/ro.yml index 343d8c1d..874e4e30 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -939,3 +939,12 @@ ro: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 63bcb4e2..46f75303 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1059,3 +1059,12 @@ ru: label_git_path: Путь к каталогу .git label_mercurial_path: Каталог label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/sk.yml b/config/locales/sk.yml index a7430f76..f50585d3 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -941,3 +941,12 @@ sk: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 9ab3c8c2..7003abef 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -942,3 +942,12 @@ sl: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/sr-YU.yml b/config/locales/sr-YU.yml index 1f4674ab..b0e13450 100644 --- a/config/locales/sr-YU.yml +++ b/config/locales/sr-YU.yml @@ -946,3 +946,12 @@ sr-YU: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 1118f3a1..14dbfaef 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -947,3 +947,12 @@ sr: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 26f0b892..a65a54e3 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -991,3 +991,9 @@ sv: label_git_path: Path to .git directory label_mercurial_path: Root directory + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news diff --git a/config/locales/th.yml b/config/locales/th.yml index 78ed93a6..2362f715 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -943,3 +943,12 @@ th: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/tr.yml b/config/locales/tr.yml index b066ff20..a56bc229 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -965,3 +965,12 @@ tr: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/uk.yml b/config/locales/uk.yml index ed100385..83e0e2d9 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -942,3 +942,12 @@ uk: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 48be079c..354ea263 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -997,3 +997,12 @@ vi: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page. diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 10f910ed..664db7ea 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1031,3 +1031,9 @@ label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 2473eac1..4b2b4004 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -960,3 +960,12 @@ zh: label_git_path: Path to .git directory label_mercurial_path: Root directory label_my_queries: My custom queries + label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee + text_journal_changed_no_detail: "%{label} updated" + button_expand_all: Expand all + button_collapse_all: Collapse all + label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author + field_effective_date: Due date + label_news_comment_added: Comment added to a news + field_warn_on_leaving_unsaved: Warn me when leaving a page with unsaved text + text_warn_on_leaving_unsaved: The current page contains unsaved text that will be lost if you leave this page.