Merge branch 'feature/rails3' into feature/rails3.2

Conflicts:
	Gemfile
	Gemfile.lock
pull/1186/head
Philipp Tessenow 12 years ago
commit 7c301cfaf9
  1. 16
      Gemfile
  2. 43
      Gemfile.lock
  3. 52
      Guardfile
  4. 5
      app/helpers/attachments_helper.rb
  5. 5
      app/helpers/issues_helper.rb
  6. 11
      app/helpers/repositories_helper.rb
  7. 8
      app/helpers/timelog_helper.rb
  8. 6
      app/models/changeset.rb
  9. 1
      app/models/ldap_auth_source.rb
  10. 7
      config/database.yml.example
  11. 2
      config/initializers/bullet.rb
  12. 8
      lib/redmine/export/pdf.rb
  13. 6
      lib/redmine/scm/adapters/abstract_adapter.rb
  14. 16
      lib/redmine/scm/adapters/filesystem_adapter.rb
  15. 18
      lib/redmine/scm/adapters/git_adapter.rb
  16. 16
      lib/redmine/scm/adapters/mercurial_adapter.rb
  17. 10
      lib/tasks/migrate_from_mantis.rake
  18. 10
      lib/tasks/migrate_from_trac.rake
  19. 27
      spec/models/project_spec.rb
  20. 126
      spec/spec_helper.rb

@ -39,14 +39,18 @@ group :test do
gem 'mocha' gem 'mocha'
gem "launchy", "~> 2.1.0" gem "launchy", "~> 2.1.0"
gem "factory_girl_rails", "~> 4.0" gem "factory_girl_rails", "~> 4.0"
gem 'cucumber-rails' gem 'cucumber-rails', :require => false
gem 'database_cleaner' gem 'database_cleaner'
gem "rspec-rails", "~> 2.0", :group => :development gem "rspec-rails", "~> 2.0", :group => :development
gem 'capybara' gem 'capybara'
gem 'spork-rails'
gem 'spork-testunit' # needed for test-unit only
gem 'ruby-debug', :platforms => [:mri_18, :mingw_18] gem 'ruby-debug', :platforms => [:mri_18, :mingw_18]
# TODO: remove dependency to v 1.1.3 when pry-debugger is updated to > 0.2 # TODO: remove dependency to v 1.1.3 when pry-debugger is updated to > 0.2
gem 'debugger', '~> 1.1.3', :platforms => [:mri_19, :mingw_19] gem 'debugger', '~> 1.1.3', :platforms => [:mri_19, :mingw_19]
# why in Gemfile? see: https://github.com/guard/guard-test
gem 'ruby-prof'
end end
group :openid do group :openid do
@ -57,6 +61,11 @@ group :development do
gem 'rails-footnotes', '>= 3.7.5.rc4' gem 'rails-footnotes', '>= 3.7.5.rc4'
gem 'bullet' gem 'bullet'
gem 'letter_opener', '~> 1.0.0' gem 'letter_opener', '~> 1.0.0'
gem 'rails-dev-tweaks', '~> 0.6.1'
gem 'guard-rspec'
gem 'guard-cucumber'
gem 'guard-spork'
gem 'rb-fsevent', :group => :test, :require => false if RUBY_PLATFORM =~ /darwin/i
end end
group :development, :test do group :development, :test do
@ -67,6 +76,11 @@ group :development, :test do
gem 'pry-doc' gem 'pry-doc'
end end
group :tools do
# why tools? see: https://github.com/guard/guard-test
gem 'guard-test'
end
group :rmagick do group :rmagick do
gem "rmagick", ">= 1.15.17" gem "rmagick", ">= 1.15.17"
# Older distributions might not have a sufficiently new ImageMagick version # Older distributions might not have a sufficiently new ImageMagick version

@ -104,6 +104,25 @@ GEM
ffi (1.1.5) ffi (1.1.5)
gherkin (2.11.5) gherkin (2.11.5)
json (>= 1.4.6) json (>= 1.4.6)
guard (1.5.0)
listen (>= 0.4.2)
lumberjack (>= 1.0.2)
pry (>= 0.9.10)
thor (>= 0.14.6)
guard-cucumber (1.2.0)
cucumber (>= 1.2.0)
guard (>= 1.1.0)
guard-rspec (2.1.0)
guard (>= 1.1)
rspec (~> 2.11)
guard-spork (1.2.1)
childprocess (>= 0.2.3)
guard (>= 1.1)
spork (>= 0.8.4)
sys-proctable
guard-test (0.5.0)
guard (>= 1.1.0)
test-unit (~> 2.2)
hike (1.2.1) hike (1.2.1)
htmldiff (0.0.1) htmldiff (0.0.1)
i18n (0.6.1) i18n (0.6.1)
@ -121,8 +140,10 @@ GEM
addressable addressable
linecache (0.46) linecache (0.46)
rbx-require-relative (> 0.0.4) rbx-require-relative (> 0.0.4)
listen (0.5.3)
loofah (1.2.1) loofah (1.2.1)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
lumberjack (1.0.2)
mail (2.4.4) mail (2.4.4)
i18n (>= 0.4.0) i18n (>= 0.4.0)
mime-types (~> 1.16) mime-types (~> 1.16)
@ -175,6 +196,9 @@ GEM
activesupport (= 3.2.8) activesupport (= 3.2.8)
bundler (~> 1.0) bundler (~> 1.0)
railties (= 3.2.8) railties (= 3.2.8)
rails-dev-tweaks (0.6.1)
actionpack (~> 3.1)
railties (~> 3.1)
rails-footnotes (3.7.8) rails-footnotes (3.7.8)
rails (>= 3.0.0) rails (>= 3.0.0)
rails_autolink (1.0.9) rails_autolink (1.0.9)
@ -210,6 +234,7 @@ GEM
ruby-debug-base (0.10.4) ruby-debug-base (0.10.4)
linecache (>= 0.3) linecache (>= 0.3)
ruby-openid (2.1.8) ruby-openid (2.1.8)
ruby-prof (0.11.2)
rubytree (0.8.3) rubytree (0.8.3)
json (>= 1.7.5) json (>= 1.7.5)
structured_warnings (>= 0.1.3) structured_warnings (>= 0.1.3)
@ -231,13 +256,21 @@ GEM
shoulda-matchers (1.4.1) shoulda-matchers (1.4.1)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
slop (3.3.3) slop (3.3.3)
sprockets (2.1.3) spork (1.0.0rc3)
spork-rails (3.2.0)
rails (>= 3.0.0, < 3.3.0)
spork (>= 1.0rc0)
spork-testunit (0.0.8)
hike (~> 1.2) hike (~> 1.2)
rack (~> 1.0) rack (~> 1.0)
spork (>= 0.6.0)
tilt (~> 1.1, != 1.3.0) tilt (~> 1.1, != 1.3.0)
sprockets (2.1.3)
sqlite3 (1.3.6) sqlite3 (1.3.6)
sqlite3-ruby (1.2.5) sqlite3-ruby (1.2.5)
structured_warnings (0.1.3) structured_warnings (0.1.3)
sys-proctable (0.9.2)
test-unit (2.5.2)
thor (0.16.0) thor (0.16.0)
tilt (1.3.3) tilt (1.3.3)
tinymce-rails (3.5.7.1) tinymce-rails (3.5.7.1)
@ -275,6 +308,10 @@ DEPENDENCIES
factory_girl_rails (~> 4.0) factory_girl_rails (~> 4.0)
fastercsv (~> 1.5.0) fastercsv (~> 1.5.0)
globalize3! globalize3!
guard-cucumber
guard-rspec
guard-spork
guard-test
htmldiff htmldiff
jquery-rails jquery-rails
jruby-openssl jruby-openssl
@ -293,6 +330,7 @@ DEPENDENCIES
pry-rescue pry-rescue
pry-stack_explorer pry-stack_explorer
rails (= 3.2.8) rails (= 3.2.8)
rails-dev-tweaks (~> 0.6.1)
rails-footnotes (>= 3.7.5.rc4) rails-footnotes (>= 3.7.5.rc4)
rails_autolink rails_autolink
rdoc (>= 2.4.2) rdoc (>= 2.4.2)
@ -300,9 +338,12 @@ DEPENDENCIES
rspec-rails (~> 2.0) rspec-rails (~> 2.0)
ruby-debug ruby-debug
ruby-openid (~> 2.1.4) ruby-openid (~> 2.1.4)
ruby-prof
rubytree (~> 0.8.3) rubytree (~> 0.8.3)
sass-rails (~> 3.2.3) sass-rails (~> 3.2.3)
shoulda (~> 3.1.1) shoulda (~> 3.1.1)
spork-rails
spork-testunit
sqlite3 sqlite3
sqlite3-ruby (< 1.3) sqlite3-ruby (< 1.3)
tinymce-rails tinymce-rails

@ -0,0 +1,52 @@
# :spork guard must come first
# guard :spork, :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
# watch('config/application.rb')
# watch('config/environment.rb')
# watch('config/environments/test.rb')
# watch(%r{^config/initializers/.+\.rb$})
# watch('Gemfile')
# watch('Gemfile.lock')
# watch('spec/spec_helper.rb') { :rspec }
# watch(%r{^spec/support/.+\.rb$}) { :rspec }
# watch('test/test_helper.rb') { :test }
# watch(%r{features/support/}) { :cucumber }
# end
# guard :rspec, :cli => "--drb" do
# watch(%r{^spec/.+_spec\.rb$})
# watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
# watch('spec/spec_helper.rb') { "spec" }
#
# # Rails example
# watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
# watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
# watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
# watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
# watch('config/routes.rb') { "spec/routing" }
# watch('app/controllers/application_controller.rb') { "spec/controllers" }
#
# # Capybara request specs
# watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
#
# # Turnip features and steps
# watch(%r{^spec/acceptance/(.+)\.feature$})
# watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
# end
#
# guard :cucumber do # , :cli => "--drb" do
# watch(%r{^features/.+\.feature$})
# watch(%r{^features/support/.+$}) { 'features' }
# watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
# end
guard :test, :all_on_start => false, :all_after_pass => false do # , :drb => true do
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
watch(%r{^test/.+_test\.rb$})
watch('test/test_helper.rb') { "test" }
# Rails example
watch(%r{^app/models/(.+)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
watch(%r{^app/controllers/(.+)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
watch(%r{^app/views/.+\.rb$}) { "test/integration" }
watch('app/controllers/application_controller.rb') { ["test/functional", "test/integration"] }
end

@ -34,9 +34,8 @@ module AttachmentsHelper
end end
begin begin
Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3] (str + ' ').encode("UTF-8", :invalid => :replace, :undef => :replace, :replace => "?")[0..-3]
rescue Iconv::InvalidEncoding rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError
# "UTF-8//IGNORE" is not supported on some OS
str str
end end
end end

@ -158,7 +158,6 @@ module IssuesHelper
end end
def issues_to_csv(issues, project = nil) def issues_to_csv(issues, project = nil)
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
decimal_separator = l(:general_csv_decimal_separator) decimal_separator = l(:general_csv_decimal_separator)
export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
# csv header fields # csv header fields
@ -186,7 +185,7 @@ module IssuesHelper
custom_fields.each {|f| headers << f.name} custom_fields.each {|f| headers << f.name}
# Description in the last column # Description in the last column
headers << l(:field_description) headers << l(:field_description)
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end } csv << headers.collect {|c| begin; c.to_s.encode(l(:general_csv_encoding), 'UTF-8'); rescue; c.to_s; end }
# csv lines # csv lines
issues.each do |issue| issues.each do |issue|
fields = [issue.id, fields = [issue.id,
@ -209,7 +208,7 @@ module IssuesHelper
] ]
custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) } custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
fields << issue.description fields << issue.description
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end } csv << fields.collect {|c| begin; c.to_s.encode(l(:general_csv_encoding), 'UTF-8'); rescue; c.to_s; end }
end end
end end
export export

@ -12,8 +12,6 @@
# See doc/COPYRIGHT.rdoc for more details. # See doc/COPYRIGHT.rdoc for more details.
#++ #++
require 'iconv'
module RepositoriesHelper module RepositoriesHelper
def format_revision(revision) def format_revision(revision)
if revision.respond_to? :format_identifier if revision.respond_to? :format_identifier
@ -135,8 +133,8 @@ module RepositoriesHelper
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip) @encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
@encodings.each do |encoding| @encodings.each do |encoding|
begin begin
return Iconv.conv('UTF-8', encoding, str) return str.to_s.encode('UTF-8', encoding)
rescue Iconv::Failure rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError
# do nothing here and try the next encoding # do nothing here and try the next encoding
end end
end end
@ -155,9 +153,8 @@ module RepositoriesHelper
else else
# removes invalid UTF8 sequences # removes invalid UTF8 sequences
begin begin
str = Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3] (str + ' ').encode("UTF-8", :invalid => :replace, :undef => :replace, :replace => "?")[0..-3]
rescue Iconv::InvalidEncoding rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError
# "UTF-8//IGNORE" is not supported on some OS
end end
end end
str str

@ -81,7 +81,6 @@ module TimelogHelper
end end
def entries_to_csv(entries) def entries_to_csv(entries)
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
decimal_separator = l(:general_csv_decimal_separator) decimal_separator = l(:general_csv_decimal_separator)
custom_fields = TimeEntryCustomField.find(:all) custom_fields = TimeEntryCustomField.find(:all)
export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
@ -99,7 +98,7 @@ module TimelogHelper
# Export custom fields # Export custom fields
headers += custom_fields.collect(&:name) headers += custom_fields.collect(&:name)
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end } csv << headers.collect {|c| begin; c.to_s.encode(l(:general_csv_encoding), 'UTF-8'); rescue; c.to_s; end }
# csv lines # csv lines
entries.each do |entry| entries.each do |entry|
fields = [format_date(entry.spent_on), fields = [format_date(entry.spent_on),
@ -114,7 +113,7 @@ module TimelogHelper
] ]
fields += custom_fields.collect {|f| show_value(entry.custom_value_for(f)) } fields += custom_fields.collect {|f| show_value(entry.custom_value_for(f)) }
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end } csv << fields.collect {|c| begin; c.to_s.encode(l(:general_csv_encoding), 'UTF-8'); rescue; c.to_s; end }
end end
end end
export export
@ -181,8 +180,7 @@ module TimelogHelper
end end
def to_utf8_for_timelogs(s) def to_utf8_for_timelogs(s)
@ic ||= Iconv.new(l(:general_csv_encoding), 'UTF-8') begin; s.to_s.encode(l(:general_csv_encoding), 'UTF-8'); rescue; s.to_s; end
begin; @ic.iconv(s.to_s); rescue; s.to_s; end
end end
def polymorphic_time_entries_path(object) def polymorphic_time_entries_path(object)

@ -12,8 +12,6 @@
# See doc/COPYRIGHT.rdoc for more details. # See doc/COPYRIGHT.rdoc for more details.
#++ #++
require 'iconv'
class Changeset < ActiveRecord::Base class Changeset < ActiveRecord::Base
belongs_to :repository belongs_to :repository
belongs_to :user belongs_to :user
@ -286,8 +284,8 @@ class Changeset < ActiveRecord::Base
txtar = "" txtar = ""
begin begin
txtar += Iconv.new('UTF-8', normalized_encoding).iconv(str) txtar += str.encode('UTF-8', normalized_encoding)
rescue Iconv::IllegalSequence rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError
txtar += $!.success txtar += $!.success
str = '?' + $!.failed[1,$!.failed.length] str = '?' + $!.failed[1,$!.failed.length]
retry retry

@ -13,7 +13,6 @@
#++ #++
require 'net/ldap' require 'net/ldap'
require 'iconv'
class LdapAuthSource < AuthSource class LdapAuthSource < AuthSource
validates_presence_of :host, :port, :attr_login validates_presence_of :host, :port, :attr_login

@ -29,10 +29,11 @@ test:
test_pgsql: test_pgsql:
adapter: postgresql adapter: postgresql
encoding: unicode
database: chiliproject_test database: chiliproject_test
host: localhost pool: 5
username: postgres username: chiliproject
password: "postgres" password:
test_sqlite3: test_sqlite3:
adapter: sqlite3 adapter: sqlite3

@ -3,7 +3,7 @@ if defined?(Bullet) && Rails.env.development?
config.after_initialize do config.after_initialize do
Bullet.enable = true Bullet.enable = true
# Bullet.alert = true # Bullet.alert = true
Bullet.bullet_logger = true Bullet.bullet_logger = true if File.directory?('log') # fails if run from an engine
Bullet.console = true Bullet.console = true
# Bullet.growl = true # Bullet.growl = true
Bullet.rails_logger = true Bullet.rails_logger = true

@ -12,7 +12,6 @@
# See doc/COPYRIGHT.rdoc for more details. # See doc/COPYRIGHT.rdoc for more details.
#++ #++
require 'iconv'
require 'rfpdf/fpdf' require 'rfpdf/fpdf'
require 'fpdf/chinese' require 'fpdf/chinese'
require 'fpdf/japanese' require 'fpdf/japanese'
@ -43,7 +42,7 @@ module Redmine
def SetTitle(txt) def SetTitle(txt)
txt = begin txt = begin
utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt) utf16txt = txt.to_s.encode('UTF-16BE', 'UTF-8')
hextxt = "<FEFF" # FEFF is BOM hextxt = "<FEFF" # FEFF is BOM
hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
hextxt << ">" hextxt << ">"
@ -118,7 +117,7 @@ module Redmine
def SetTitle(txt) def SetTitle(txt)
txt = begin txt = begin
utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt) utf16txt = txt.to_s.encode('UTF-16BE', 'UTF-8')
hextxt = "<FEFF" # FEFF is BOM hextxt = "<FEFF" # FEFF is BOM
hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
hextxt << ">" hextxt << ">"
@ -138,14 +137,13 @@ module Redmine
end end
def fix_text_encoding(txt) def fix_text_encoding(txt)
@ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
# these quotation marks are not correctly rendered in the pdf # these quotation marks are not correctly rendered in the pdf
txt = txt.gsub(/[“â€<EFBFBD>]/, '"') if txt txt = txt.gsub(/[“â€<EFBFBD>]/, '"') if txt
txt = begin txt = begin
# 0x5c char handling # 0x5c char handling
txtar = txt.split('\\') txtar = txt.split('\\')
txtar << '' if txt[-1] == ?\\ txtar << '' if txt[-1] == ?\\
txtar.collect {|x| @ic.iconv(x)}.join('\\').gsub(/\\/, "\\\\\\\\") txtar.collect {|x| x.encode(l(:general_pdf_encoding), 'UTF-8')}.join('\\').gsub(/\\/, "\\\\\\\\")
rescue rescue
txt txt
end || '' end || ''

@ -225,12 +225,12 @@ module Redmine
self.class.strip_credential(cmd) self.class.strip_credential(cmd)
end end
def scm_iconv(to, from, str) def scm_encode(to, from, str)
return nil if str.nil? return nil if str.nil?
return str if to == from return str if to == from
begin begin
Iconv.conv(to, from, str) str.to_s.encode(to, from)
rescue Iconv::Failure => err rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError => err
logger.error("failed to convert from #{from} to #{to}. #{err}") logger.error("failed to convert from #{from} to #{to}. #{err}")
nil nil
end end

@ -51,23 +51,23 @@ module Redmine
def entries(path="", identifier=nil) def entries(path="", identifier=nil)
entries = Entries.new entries = Entries.new
trgt_utf8 = target(path) trgt_utf8 = target(path)
trgt = scm_iconv(@path_encoding, 'UTF-8', trgt_utf8) trgt = scm_encode(@path_encoding, 'UTF-8', trgt_utf8)
Dir.new(trgt).each do |e1| Dir.new(trgt).each do |e1|
e_utf8 = scm_iconv('UTF-8', @path_encoding, e1) e_utf8 = scm_encode('UTF-8', @path_encoding, e1)
next if e_utf8.blank? next if e_utf8.blank?
relative_path_utf8 = format_path_ends( relative_path_utf8 = format_path_ends(
(format_path_ends(path,false,true) + e_utf8),false,false) (format_path_ends(path,false,true) + e_utf8),false,false)
t1_utf8 = target(relative_path_utf8) t1_utf8 = target(relative_path_utf8)
t1 = scm_iconv(@path_encoding, 'UTF-8', t1_utf8) t1 = scm_encode(@path_encoding, 'UTF-8', t1_utf8)
relative_path = scm_iconv(@path_encoding, 'UTF-8', relative_path_utf8) relative_path = scm_encode(@path_encoding, 'UTF-8', relative_path_utf8)
e1 = scm_iconv(@path_encoding, 'UTF-8', e_utf8) e1 = scm_encode(@path_encoding, 'UTF-8', e_utf8)
if File.exist?(t1) and # paranoid test if File.exist?(t1) and # paranoid test
%w{file directory}.include?(File.ftype(t1)) and # avoid special types %w{file directory}.include?(File.ftype(t1)) and # avoid special types
not File.basename(e1).match(/^\.+$/) # avoid . and .. not File.basename(e1).match(/^\.+$/) # avoid . and ..
p1 = File.readable?(t1) ? relative_path : "" p1 = File.readable?(t1) ? relative_path : ""
utf_8_path = scm_iconv('UTF-8', @path_encoding, p1) utf_8_path = scm_encode('UTF-8', @path_encoding, p1)
entries << entries <<
Entry.new({ :name => scm_iconv('UTF-8', @path_encoding, File.basename(e1)), Entry.new({ :name => scm_encode('UTF-8', @path_encoding, File.basename(e1)),
# below : list unreadable files, but dont link them. # below : list unreadable files, but dont link them.
:path => utf_8_path, :path => utf_8_path,
:kind => (File.directory?(t1) ? 'dir' : 'file'), :kind => (File.directory?(t1) ? 'dir' : 'file'),
@ -84,7 +84,7 @@ module Redmine
end end
def cat(path, identifier=nil) def cat(path, identifier=nil)
p = scm_iconv(@path_encoding, 'UTF-8', target(path)) p = scm_encode(@path_encoding, 'UTF-8', target(path))
File.new(p, "rb").read File.new(p, "rb").read
rescue => err rescue => err
logger.error "scm: filesystem: error: #{err.message}" logger.error "scm: filesystem: error: #{err.message}"

@ -105,7 +105,7 @@ module Redmine
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
path ||= '' path ||= ''
p = scm_iconv(@path_encoding, 'UTF-8', path) p = scm_encode(@path_encoding, 'UTF-8', path)
entries = Entries.new entries = Entries.new
cmd_args = %w|ls-tree -l| cmd_args = %w|ls-tree -l|
cmd_args << "HEAD:#{p}" if identifier.nil? cmd_args << "HEAD:#{p}" if identifier.nil?
@ -122,8 +122,8 @@ module Redmine
name.force_encoding(@path_encoding) name.force_encoding(@path_encoding)
end end
full_path = p.empty? ? name : "#{p}/#{name}" full_path = p.empty? ? name : "#{p}/#{name}"
n = scm_iconv('UTF-8', @path_encoding, name) n = scm_encode('UTF-8', @path_encoding, name)
full_p = scm_iconv('UTF-8', @path_encoding, full_path) full_p = scm_encode('UTF-8', @path_encoding, full_path)
entries << Entry.new({:name => n, entries << Entry.new({:name => n,
:path => full_p, :path => full_p,
:kind => (type == "tree") ? 'dir' : 'file', :kind => (type == "tree") ? 'dir' : 'file',
@ -177,7 +177,7 @@ module Redmine
from_to << "#{identifier_to}" if identifier_to from_to << "#{identifier_to}" if identifier_to
cmd_args << from_to if !from_to.empty? 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 << "--since=#{options[:since].strftime("%Y-%m-%d %H:%M:%S")}" if options[:since]
cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty? cmd_args << "--" << scm_encode(@path_encoding, 'UTF-8', path) if path && !path.empty?
scm_cmd *cmd_args do |io| scm_cmd *cmd_args do |io|
files=[] files=[]
@ -223,14 +223,14 @@ module Redmine
parsing_descr = 2 parsing_descr = 2
fileaction = $1 fileaction = $1
filepath = $2 filepath = $2
p = scm_iconv('UTF-8', @path_encoding, filepath) p = scm_encode('UTF-8', @path_encoding, filepath)
files << {:action => fileaction, :path => p} files << {:action => fileaction, :path => p}
elsif (parsing_descr == 1 || parsing_descr == 2) \ elsif (parsing_descr == 1 || parsing_descr == 2) \
&& line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/ && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/
parsing_descr = 2 parsing_descr = 2
fileaction = $1 fileaction = $1
filepath = $3 filepath = $3
p = scm_iconv('UTF-8', @path_encoding, filepath) p = scm_encode('UTF-8', @path_encoding, filepath)
files << {:action => fileaction, :path => p} files << {:action => fileaction, :path => p}
elsif (parsing_descr == 1) && line.chomp.to_s == "" elsif (parsing_descr == 1) && line.chomp.to_s == ""
parsing_descr = 2 parsing_descr = 2
@ -269,7 +269,7 @@ module Redmine
else else
cmd_args << "show" << "--no-color" << identifier_from cmd_args << "show" << "--no-color" << identifier_from
end end
cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty? cmd_args << "--" << scm_encode(@path_encoding, 'UTF-8', path) unless path.empty?
diff = [] diff = []
scm_cmd *cmd_args do |io| scm_cmd *cmd_args do |io|
io.each_line do |line| io.each_line do |line|
@ -284,7 +284,7 @@ module Redmine
def annotate(path, identifier=nil) def annotate(path, identifier=nil)
identifier = 'HEAD' if identifier.blank? identifier = 'HEAD' if identifier.blank?
cmd_args = %w|blame| cmd_args = %w|blame|
cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path) cmd_args << "-p" << identifier << "--" << scm_encode(@path_encoding, 'UTF-8', path)
blame = Annotate.new blame = Annotate.new
content = nil content = nil
scm_cmd(*cmd_args) { |io| io.binmode; content = io.read } scm_cmd(*cmd_args) { |io| io.binmode; content = io.read }
@ -321,7 +321,7 @@ module Redmine
identifier = 'HEAD' identifier = 'HEAD'
end end
cmd_args = %w|show --no-color| cmd_args = %w|show --no-color|
cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}" cmd_args << "#{identifier}:#{scm_encode(@path_encoding, 'UTF-8', path)}"
cat = nil cat = nil
scm_cmd(*cmd_args) do |io| scm_cmd(*cmd_args) do |io|
io.binmode io.binmode

@ -130,7 +130,7 @@ module Redmine
private :summary private :summary
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
p1 = scm_iconv(@path_encoding, 'UTF-8', path) p1 = scm_encode(@path_encoding, 'UTF-8', path)
manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)), manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)),
CGI.escape(without_leading_slash(p1.to_s))) do |io| CGI.escape(without_leading_slash(p1.to_s))) do |io|
output = io.read output = io.read
@ -146,13 +146,13 @@ module Redmine
entries = Entries.new entries = Entries.new
as_ary(manifest['dir']).each do |e| as_ary(manifest['dir']).each do |e|
n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name'])) n = scm_encode('UTF-8', @path_encoding, CGI.unescape(e['name']))
p = "#{path_prefix}#{n}" p = "#{path_prefix}#{n}"
entries << Entry.new(:name => n, :path => p, :kind => 'dir') entries << Entry.new(:name => n, :path => p, :kind => 'dir')
end end
as_ary(manifest['file']).each do |e| as_ary(manifest['file']).each do |e|
n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name'])) n = scm_encode('UTF-8', @path_encoding, CGI.unescape(e['name']))
p = "#{path_prefix}#{n}" p = "#{path_prefix}#{n}"
lr = Revision.new(:revision => e['revision'], :scmid => e['node'], lr = Revision.new(:revision => e['revision'], :scmid => e['node'],
:identifier => e['node'], :identifier => e['node'],
@ -194,13 +194,13 @@ module Redmine
as_ary(log['logentry']).each do |le| as_ary(log['logentry']).each do |le|
cpalist = as_ary(le['paths']['path-copied']).map do |e| cpalist = as_ary(le['paths']['path-copied']).map do |e|
[e['__content__'], e['copyfrom-path']].map do |s| [e['__content__'], e['copyfrom-path']].map do |s|
scm_iconv('UTF-8', @path_encoding, CGI.unescape(s)) scm_encode('UTF-8', @path_encoding, CGI.unescape(s))
end end
end end
cpmap = Hash[*cpalist.flatten] cpmap = Hash[*cpalist.flatten]
paths = as_ary(le['paths']['path']).map do |e| paths = as_ary(le['paths']['path']).map do |e|
p = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['__content__']) ) p = scm_encode('UTF-8', @path_encoding, CGI.unescape(e['__content__']) )
{:action => e['action'], :path => with_leading_slash(p), {:action => e['action'], :path => with_leading_slash(p),
:from_path => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil), :from_path => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil),
:from_revision => (cpmap.member?(p) ? le['revision'] : nil)} :from_revision => (cpmap.member?(p) ? le['revision'] : nil)}
@ -233,7 +233,7 @@ module Redmine
hg_args << '-c' << hgrev(identifier_from) hg_args << '-c' << hgrev(identifier_from)
end end
unless path.blank? unless path.blank?
p = scm_iconv(@path_encoding, 'UTF-8', path) p = scm_encode(@path_encoding, 'UTF-8', path)
hg_args << CGI.escape(hgtarget(p)) hg_args << CGI.escape(hgtarget(p))
end end
diff = [] diff = []
@ -248,7 +248,7 @@ module Redmine
end end
def cat(path, identifier=nil) def cat(path, identifier=nil)
p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path)) p = CGI.escape(scm_encode(@path_encoding, 'UTF-8', path))
hg 'rhcat', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io| hg 'rhcat', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
io.binmode io.binmode
io.read io.read
@ -258,7 +258,7 @@ module Redmine
end end
def annotate(path, identifier=nil) def annotate(path, identifier=nil)
p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path)) p = CGI.escape(scm_encode(@path_encoding, 'UTF-8', path))
blame = Annotate.new blame = Annotate.new
hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io| hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
io.each_line do |line| io.each_line do |line|

@ -16,7 +16,6 @@
desc 'Mantis migration script' desc 'Mantis migration script'
require 'active_record' require 'active_record'
require 'iconv'
require 'pp' require 'pp'
namespace :redmine do namespace :redmine do
@ -439,9 +438,9 @@ task :migrate_from_mantis => :environment do
end end
def self.encoding(charset) def self.encoding(charset)
@ic = Iconv.new('UTF-8', charset) ''.encode('UTF-8', @encoding = charset)
rescue Iconv::InvalidEncoding rescue Encoding::ConverterNotFoundError
return false false
end end
def self.establish_connection(params) def self.establish_connection(params)
@ -453,7 +452,8 @@ task :migrate_from_mantis => :environment do
end end
def self.encode(text) def self.encode(text)
@ic.iconv text @encoding ||= 'UTF-8'
text.encode('UTF-8', @encoding)
rescue rescue
text text
end end

@ -14,7 +14,6 @@
require 'active_record' require 'active_record'
require 'iconv'
require 'pp' require 'pp'
namespace :redmine do namespace :redmine do
@ -597,10 +596,10 @@ namespace :redmine do
end end
def self.encoding(charset) def self.encoding(charset)
@ic = Iconv.new('UTF-8', charset) ''.encode('UTF-8', @encoding = charset)
rescue Iconv::InvalidEncoding rescue Encoding::ConverterNotFoundError
puts "Invalid encoding!" puts "Invalid encoding!"
return false false
end end
def self.set_trac_directory(path) def self.set_trac_directory(path)
@ -709,7 +708,8 @@ namespace :redmine do
private private
def self.encode(text) def self.encode(text)
@ic.iconv text @encoding ||= 'UTF-8'
text.encode('UTF-8', @encoding)
rescue rescue
text text
end end

@ -0,0 +1,27 @@
require 'spec_helper'
describe Project do
describe Project::STATUS_ACTIVE do
it "equals 1" do
# spec that STATUS_ACTIVE has the correct value
Project::STATUS_ACTIVE.should == 1
end
end
describe "#active?" do
before do
# stub out the actual value of the constant
stub_const('Project::STATUS_ACTIVE', 42)
end
it "is active when :status equals STATUS_ACTIVE" do
project = FactoryGirl.create :project, :status => 42
project.should be_active
end
it "is not active when :status doesn't equal STATUS_ACTIVE" do
project = FactoryGirl.create :project, :status => 99
project.should_not be_active
end
end
end

@ -1,39 +1,89 @@
# This file is copied to spec/ when you run 'rails generate rspec:install' # --- Instructions ---
ENV["RAILS_ENV"] ||= 'test' # Sort the contents of this file into a Spork.prefork and a Spork.each_run
require File.expand_path("../../config/environment", __FILE__) # block.
require 'rspec/rails' #
require 'rspec/autorun' # The Spork.prefork block is run only once when the spork server is started.
require 'capybara/rails' # You typically want to place most of your (slow) initializer code in here, in
# particular, require'ing any 3rd-party gems that you don't normally modify
# Requires supporting ruby files with custom matchers and macros, etc, # during development.
# in spec/support/ and its subdirectories. #
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} # The Spork.each_run block is run each time you run your specs. In case you
# need to load files that tend to change during development, require them here.
RSpec.configure do |config| # With Rails, your application modules are loaded automatically, so sometimes
# ## Mock Framework # this block can remain empty.
# #
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: # Note: You can modify files loaded *from* the Spork.each_run block without
# # restarting the spork server. However, this file itself will not be reloaded,
# config.mock_with :mocha # so if you change any of the code inside the each_run block, you still need to
# config.mock_with :flexmock # restart the server. In general, if you have non-trivial code in this file,
# config.mock_with :rr # it's advisable to move it into a separate file so you can easily edit it
# without restarting spork. (For example, with RSpec, you could move
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures # non-trivial code into a file spec/support/my_helper.rb, making sure that the
config.fixture_path = "#{::Rails.root}/spec/fixtures" # spec/support/* files are require'd from inside the each_run block.)
#
# If you're not using ActiveRecord, or you'd prefer not to run each of your # Any code that is left outside the two blocks will be run during preforking
# examples within a transaction, remove the following line or assign false # *and* during each_run -- that's probably not what you want.
# instead of true. #
config.use_transactional_fixtures = true # These instructions should self-destruct in 10 seconds. If they don't, feel
# free to delete them.
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of require 'rubygems'
# rspec-rails. require 'spork'
config.infer_base_class_for_anonymous_controllers = false
#uncomment the following line to use spork with the debugger
# Run specs in random order to surface order dependencies. If you find an #require 'spork/ext/ruby-debug'
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run. Spork.prefork do
# --seed 1234 # Loading more in this block will cause your tests to run faster. However,
config.order = "random" # if you change any configuration or code from libraries loaded here, you'll
# need to restart spork for it take effect.
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rails'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
config.treat_symbols_as_metadata_keys_with_true_values = true
config.filter_run :focus => true
config.run_all_when_everything_filtered = true
end
end
Spork.each_run do
# This code will be run each time you run your specs.
FactoryGirl.reload
end end

Loading…
Cancel
Save