The requested changes are too big and content was truncated. Show full diff
@@ -0,0 +1,6 | |||
|
1 | #!/usr/bin/env ruby | |
|
2 | ||
|
3 | ENV["RAILS_ENV"] ||= "production" | |
|
4 | require File.expand_path(File.dirname(__FILE__) + "/../config/environment") | |
|
5 | puts | |
|
6 | puts Redmine::Info.environment |
@@ -0,0 +1,3 | |||
|
1 | #!/usr/bin/env ruby.exe | |
|
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) | |
|
3 | load Gem.bin_path('bundler', 'bundle') |
@@ -0,0 +1,4 | |||
|
1 | #!/usr/bin/env ruby.exe | |
|
2 | APP_PATH = File.expand_path('../../config/application', __FILE__) | |
|
3 | require_relative '../config/boot' | |
|
4 | require 'rails/commands' |
@@ -0,0 +1,4 | |||
|
1 | #!/usr/bin/env ruby.exe | |
|
2 | require_relative '../config/boot' | |
|
3 | require 'rake' | |
|
4 | Rake.application.run |
@@ -3,8 +3,6 | |||
|
3 | 3 | # You can also run tests on your environment. |
|
4 | 4 | language: ruby |
|
5 | 5 | rvm: |
|
6 | - 1.8.7 | |
|
7 | - 1.9.2 | |
|
8 | 6 | - 1.9.3 |
|
9 | 7 | - 2.0 |
|
10 | 8 | - 2.1 |
@@ -34,6 +32,7 script: | |||
|
34 | 32 | - "bundle install" |
|
35 | 33 | - "RUN_ON_NOT_OFFICIAL='' RUBY_VER=1.9 BRANCH=trunk bundle exec rake config/database.yml" |
|
36 | 34 | - "bundle install" |
|
37 |
- " |
|
|
35 | - "bundle exec rake ci:setup" | |
|
36 | - "sh .travis.run-test.sh" | |
|
38 | 37 | notifications: |
|
39 | 38 | email: false |
@@ -1,12 +1,17 | |||
|
1 | 1 | source 'https://rubygems.org' |
|
2 | 2 | |
|
3 |
gem "rails", " |
|
|
3 | gem "rails", "4.1.6" | |
|
4 | 4 | gem "jquery-rails", "~> 3.1.1" |
|
5 | 5 | gem "coderay", "~> 1.1.0" |
|
6 | gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] | |
|
7 | 6 | gem "builder", ">= 3.0.4" |
|
8 | 7 | gem "request_store", "1.0.5" |
|
9 | 8 | gem "mime-types" |
|
9 | gem "awesome_nested_set", "3.0.0" | |
|
10 | gem "protected_attributes" | |
|
11 | gem "actionpack-action_caching" | |
|
12 | ||
|
13 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem | |
|
14 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :jruby] | |
|
10 | 15 | gem "rbpdf", "~> 1.18.1" |
|
11 | 16 | |
|
12 | 17 | # Optional gem for LDAP authentication |
@@ -23,16 +28,12 end | |||
|
23 | 28 | platforms :mri, :mingw do |
|
24 | 29 | # Optional gem for exporting the gantt to a PNG file, not supported with jruby |
|
25 | 30 | group :rmagick do |
|
26 | # RMagick 2 supports ruby 1.9 | |
|
27 | # RMagick 1 would be fine for ruby 1.8 but Bundler does not support | |
|
28 | # different requirements for the same gem on different platforms | |
|
29 | 31 | gem "rmagick", ">= 2.0.0" |
|
30 | 32 | end |
|
31 | 33 | |
|
32 | 34 | # Optional Markdown support, not for JRuby |
|
33 | 35 | group :markdown do |
|
34 | # TODO: upgrade to redcarpet 3.x when ruby1.8 support is dropped | |
|
35 | gem "redcarpet", "~> 2.3.0" | |
|
36 | gem "redcarpet", "~> 3.1.2" | |
|
36 | 37 | end |
|
37 | 38 | end |
|
38 | 39 | |
@@ -57,7 +58,6 if File.exist?(database_file) | |||
|
57 | 58 | gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw] |
|
58 | 59 | gem "activerecord-jdbcmysql-adapter", :platforms => :jruby |
|
59 | 60 | when 'mysql' |
|
60 | gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw] | |
|
61 | 61 | gem "activerecord-jdbcmysql-adapter", :platforms => :jruby |
|
62 | 62 | when /postgresql/ |
|
63 | 63 | gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw] |
@@ -85,24 +85,20 group :development do | |||
|
85 | 85 | end |
|
86 | 86 | |
|
87 | 87 | group :test do |
|
88 | gem "shoulda", "~> 3.3.2" | |
|
89 |
gem "shoulda- |
|
|
88 | gem "minitest" | |
|
89 | gem "shoulda-context" | |
|
90 | 90 | gem "mocha", "~> 1.0.0", :require => 'mocha/api' |
|
91 | if RUBY_VERSION >= '1.9.3' | |
|
92 |
|
|
|
93 |
|
|
|
94 | end | |
|
91 | # For running UI tests | |
|
92 | gem "capybara", "~> 2.1.0" | |
|
93 | gem "selenium-webdriver" | |
|
95 | 94 | end |
|
96 | 95 | |
|
97 | 96 | local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") |
|
98 | 97 | if File.exists?(local_gemfile) |
|
99 | puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v` | |
|
100 | instance_eval File.read(local_gemfile) | |
|
98 | eval_gemfile local_gemfile | |
|
101 | 99 | end |
|
102 | 100 | |
|
103 | 101 | # Load plugins' Gemfiles |
|
104 | 102 | Dir.glob File.expand_path("../plugins/*/{Gemfile,PluginGemfile}", __FILE__) do |file| |
|
105 | puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` | |
|
106 | #TODO: switch to "eval_gemfile file" when bundler >= 1.2.0 will be required (rails 4) | |
|
107 | instance_eval File.read(file), file | |
|
103 | eval_gemfile file | |
|
108 | 104 | end |
@@ -34,7 +34,7 class AdminController < ApplicationController | |||
|
34 | 34 | |
|
35 | 35 | scope = Project.status(@status).order('lft') |
|
36 | 36 | scope = scope.like(params[:name]) if params[:name].present? |
|
37 |
@projects = scope.a |
|
|
37 | @projects = scope.to_a | |
|
38 | 38 | |
|
39 | 39 | render :action => "projects", :layout => false if request.xhr? |
|
40 | 40 | end |
@@ -496,7 +496,7 class ApplicationController < ActionController::Base | |||
|
496 | 496 | end |
|
497 | 497 | |
|
498 | 498 | def render_feed(items, options={}) |
|
499 | @items = items || [] | |
|
499 | @items = (items || []).to_a | |
|
500 | 500 | @items.sort! {|x,y| y.event_datetime <=> x.event_datetime } |
|
501 | 501 | @items = @items.slice(0, Setting.feeds_limit.to_i) |
|
502 | 502 | @title = options[:title] || Setting.app_title |
@@ -26,7 +26,7 class AutoCompletesController < ApplicationController | |||
|
26 | 26 | if q.match(/\A#?(\d+)\z/) |
|
27 | 27 | @issues << scope.find_by_id($1.to_i) |
|
28 | 28 | end |
|
29 |
@issues += scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%").order("#{Issue.table_name}.id DESC").limit(10).a |
|
|
29 | @issues += scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%").order("#{Issue.table_name}.id DESC").limit(10).to_a | |
|
30 | 30 | @issues.compact! |
|
31 | 31 | end |
|
32 | 32 | render :layout => false |
@@ -25,7 +25,7 class BoardsController < ApplicationController | |||
|
25 | 25 | helper :watchers |
|
26 | 26 | |
|
27 | 27 | def index |
|
28 |
@boards = @project.boards. |
|
|
28 | @boards = @project.boards.preload(:project, :last_message => :author).to_a | |
|
29 | 29 | # show the board if there is only one |
|
30 | 30 | if @boards.size == 1 |
|
31 | 31 | @board = @boards.first |
@@ -45,12 +45,13 class BoardsController < ApplicationController | |||
|
45 | 45 | @topic_pages = Paginator.new @topic_count, per_page_option, params['page'] |
|
46 | 46 | @topics = @board.topics. |
|
47 | 47 | reorder("#{Message.table_name}.sticky DESC"). |
|
48 | includes(:last_reply). | |
|
48 | joins("LEFT OUTER JOIN #{Message.table_name} last_replies_messages ON last_replies_messages.id = #{Message.table_name}.last_reply_id"). | |
|
49 | references(:last_reply). | |
|
49 | 50 | limit(@topic_pages.per_page). |
|
50 | 51 | offset(@topic_pages.offset). |
|
51 | 52 | order(sort_clause). |
|
52 | 53 | preload(:author, {:last_reply => :author}). |
|
53 |
a |
|
|
54 | to_a | |
|
54 | 55 | @message = Message.new(:board => @board) |
|
55 | 56 | render :action => 'show', :layout => !request.xhr? |
|
56 | 57 | } |
@@ -59,7 +60,7 class BoardsController < ApplicationController | |||
|
59 | 60 | reorder('created_on DESC'). |
|
60 | 61 | includes(:author, :board). |
|
61 | 62 | limit(Setting.feeds_limit.to_i). |
|
62 |
a |
|
|
63 | to_a | |
|
63 | 64 | render_feed(@messages, :title => "#{@project}: #{@board}") |
|
64 | 65 | } |
|
65 | 66 | end |
@@ -27,7 +27,7 class DocumentsController < ApplicationController | |||
|
27 | 27 | |
|
28 | 28 | def index |
|
29 | 29 | @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category' |
|
30 |
documents = @project.documents.includes(:attachments, :category).a |
|
|
30 | documents = @project.documents.includes(:attachments, :category).to_a | |
|
31 | 31 | case @sort_by |
|
32 | 32 | when 'date' |
|
33 | 33 | @grouped = documents.group_by {|d| d.updated_on.to_date } |
@@ -43,7 +43,7 class DocumentsController < ApplicationController | |||
|
43 | 43 | end |
|
44 | 44 | |
|
45 | 45 | def show |
|
46 |
@attachments = @document.attachments.a |
|
|
46 | @attachments = @document.attachments.to_a | |
|
47 | 47 | end |
|
48 | 48 | |
|
49 | 49 | def new |
@@ -69,7 +69,7 class DocumentsController < ApplicationController | |||
|
69 | 69 | |
|
70 | 70 | def update |
|
71 | 71 | @document.safe_attributes = params[:document] |
|
72 |
if |
|
|
72 | if @document.save | |
|
73 | 73 | flash[:notice] = l(:notice_successful_update) |
|
74 | 74 | redirect_to document_path(@document) |
|
75 | 75 | else |
@@ -32,7 +32,7 class EnumerationsController < ApplicationController | |||
|
32 | 32 | format.api { |
|
33 | 33 | @klass = Enumeration.get_subclass(params[:type]) |
|
34 | 34 | if @klass |
|
35 |
@enumerations = @klass.shared.sorted.a |
|
|
35 | @enumerations = @klass.shared.sorted.to_a | |
|
36 | 36 | else |
|
37 | 37 | render_404 |
|
38 | 38 | end |
@@ -56,7 +56,7 class EnumerationsController < ApplicationController | |||
|
56 | 56 | end |
|
57 | 57 | |
|
58 | 58 | def update |
|
59 |
if |
|
|
59 | if @enumeration.update_attributes(params[:enumeration]) | |
|
60 | 60 | flash[:notice] = l(:notice_successful_update) |
|
61 | 61 | redirect_to enumerations_path |
|
62 | 62 | else |
@@ -75,7 +75,7 class EnumerationsController < ApplicationController | |||
|
75 | 75 | redirect_to enumerations_path |
|
76 | 76 | return |
|
77 | 77 | end |
|
78 |
@enumerations = @enumeration.class.system.a |
|
|
78 | @enumerations = @enumeration.class.system.to_a - [@enumeration] | |
|
79 | 79 | end |
|
80 | 80 | |
|
81 | 81 | private |
@@ -31,8 +31,10 class FilesController < ApplicationController | |||
|
31 | 31 | 'size' => "#{Attachment.table_name}.filesize", |
|
32 | 32 | 'downloads' => "#{Attachment.table_name}.downloads" |
|
33 | 33 | |
|
34 |
@containers = [ |
|
|
35 | @containers += @project.versions.includes(:attachments).reorder(sort_clause).all.sort.reverse | |
|
34 | @containers = [Project.includes(:attachments). | |
|
35 | references(:attachments).reorder(sort_clause).find(@project.id)] | |
|
36 | @containers += @project.versions.includes(:attachments). | |
|
37 | references(:attachments).reorder(sort_clause).to_a.sort.reverse | |
|
36 | 38 | render :layout => !request.xhr? |
|
37 | 39 | end |
|
38 | 40 |
@@ -27,13 +27,13 class GroupsController < ApplicationController | |||
|
27 | 27 | def index |
|
28 | 28 | respond_to do |format| |
|
29 | 29 | format.html { |
|
30 |
@groups = Group.sorted.a |
|
|
30 | @groups = Group.sorted.to_a | |
|
31 | 31 | @user_count_by_group_id = user_count_by_group_id |
|
32 | 32 | } |
|
33 | 33 | format.api { |
|
34 | 34 | scope = Group.sorted |
|
35 | 35 | scope = scope.givable unless params[:builtin] == '1' |
|
36 |
@groups = scope.a |
|
|
36 | @groups = scope.to_a | |
|
37 | 37 | } |
|
38 | 38 | end |
|
39 | 39 | end |
@@ -95,7 +95,7 class GroupsController < ApplicationController | |||
|
95 | 95 | end |
|
96 | 96 | |
|
97 | 97 | def add_users |
|
98 |
@users = User.where(:id => (params[:user_id] || params[:user_ids])).a |
|
|
98 | @users = User.where(:id => (params[:user_id] || params[:user_ids])).to_a | |
|
99 | 99 | @group.users << @users if request.post? |
|
100 | 100 | respond_to do |format| |
|
101 | 101 | format.html { redirect_to edit_group_path(@group, :tab => 'users') } |
@@ -27,7 +27,7 class IssueCategoriesController < ApplicationController | |||
|
27 | 27 | def index |
|
28 | 28 | respond_to do |format| |
|
29 | 29 | format.html { redirect_to_settings_in_projects } |
|
30 |
format.api { @categories = @project.issue_categories.a |
|
|
30 | format.api { @categories = @project.issue_categories.to_a } | |
|
31 | 31 | end |
|
32 | 32 | end |
|
33 | 33 |
@@ -29,7 +29,7 class IssueStatusesController < ApplicationController | |||
|
29 | 29 | render :action => "index", :layout => false if request.xhr? |
|
30 | 30 | } |
|
31 | 31 | format.api { |
|
32 |
@issue_statuses = IssueStatus.order('position').a |
|
|
32 | @issue_statuses = IssueStatus.order('position').to_a | |
|
33 | 33 | } |
|
34 | 34 | end |
|
35 | 35 | end |
@@ -104,15 +104,16 class IssuesController < ApplicationController | |||
|
104 | 104 | end |
|
105 | 105 | |
|
106 | 106 | def show |
|
107 |
@journals = @issue.journals.includes(:user, :details). |
|
|
107 | @journals = @issue.journals.includes(:user, :details). | |
|
108 | references(:user, :details). | |
|
109 | reorder("#{Journal.table_name}.id ASC").to_a | |
|
108 | 110 | @journals.each_with_index {|j,i| j.indice = i+1} |
|
109 | 111 | @journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project) |
|
110 | 112 | Journal.preload_journals_details_custom_fields(@journals) |
|
111 | # TODO: use #select! when ruby1.8 support is dropped | |
|
112 | @journals.reject! {|journal| !journal.notes? && journal.visible_details.empty?} | |
|
113 | @journals.select! {|journal| journal.notes? || journal.visible_details.any?} | |
|
113 | 114 | @journals.reverse! if User.current.wants_comments_in_reverse_order? |
|
114 | 115 | |
|
115 |
@changesets = @issue.changesets.visible.a |
|
|
116 | @changesets = @issue.changesets.visible.to_a | |
|
116 | 117 | @changesets.reverse! if User.current.wants_comments_in_reverse_order? |
|
117 | 118 | |
|
118 | 119 | @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? } |
@@ -189,7 +190,7 class IssuesController < ApplicationController | |||
|
189 | 190 | rescue ActiveRecord::StaleObjectError |
|
190 | 191 | @conflict = true |
|
191 | 192 | if params[:last_journal_id] |
|
192 |
@conflict_journals = @issue.journals_after(params[:last_journal_id]).a |
|
|
193 | @conflict_journals = @issue.journals_after(params[:last_journal_id]).to_a | |
|
193 | 194 | @conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project) |
|
194 | 195 | end |
|
195 | 196 | end |
@@ -301,7 +302,7 class IssuesController < ApplicationController | |||
|
301 | 302 | else |
|
302 | 303 | @saved_issues = @issues |
|
303 | 304 | @unsaved_issues = unsaved_issues |
|
304 |
@issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).a |
|
|
305 | @issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).to_a | |
|
305 | 306 | bulk_edit |
|
306 | 307 | render :action => 'bulk_edit' |
|
307 | 308 | end |
@@ -375,7 +376,9 class IssuesController < ApplicationController | |||
|
375 | 376 | def update_issue_from_params |
|
376 | 377 | @edit_allowed = User.current.allowed_to?(:edit_issues, @project) |
|
377 | 378 | @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project) |
|
378 |
|
|
|
379 | if params[:time_entry] | |
|
380 | @time_entry.attributes = params[:time_entry] | |
|
381 | end | |
|
379 | 382 | |
|
380 | 383 | @issue.init_journal(User.current) |
|
381 | 384 | |
@@ -422,7 +425,9 class IssuesController < ApplicationController | |||
|
422 | 425 | @issue.project = @project |
|
423 | 426 | @issue.author ||= User.current |
|
424 | 427 | # Tracker must be set before custom field values |
|
425 |
|
|
|
428 | tracker_id = (params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] | |
|
429 | tracker = tracker_id.present? ? @project.trackers.find(tracker_id) : @project.trackers.first | |
|
430 | @issue.tracker ||= tracker | |
|
426 | 431 | if @issue.tracker.nil? |
|
427 | 432 | render_error l(:error_no_tracker_in_project) |
|
428 | 433 | return false |
@@ -34,7 +34,6 class JournalsController < ApplicationController | |||
|
34 | 34 | retrieve_query |
|
35 | 35 | sort_init 'id', 'desc' |
|
36 | 36 | sort_update(@query.sortable_columns) |
|
37 | ||
|
38 | 37 | if @query.valid? |
|
39 | 38 | @journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC", |
|
40 | 39 | :limit => 25) |
@@ -32,7 +32,7 class MembersController < ApplicationController | |||
|
32 | 32 | order("#{Member.table_name}.id"). |
|
33 | 33 | limit(@limit). |
|
34 | 34 | offset(@offset). |
|
35 |
a |
|
|
35 | to_a | |
|
36 | 36 | respond_to do |format| |
|
37 | 37 | format.html { head 406 } |
|
38 | 38 | format.api |
@@ -63,7 +63,10 class MembersController < ApplicationController | |||
|
63 | 63 | |
|
64 | 64 | respond_to do |format| |
|
65 | 65 | format.html { redirect_to_settings_in_projects } |
|
66 |
format.js { |
|
|
66 | format.js { | |
|
67 | @members = members | |
|
68 | @member = Member.new | |
|
69 | } | |
|
67 | 70 | format.api { |
|
68 | 71 | @member = members.first |
|
69 | 72 | if @member.valid? |
@@ -43,10 +43,10 class MessagesController < ApplicationController | |||
|
43 | 43 | @reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page |
|
44 | 44 | @replies = @topic.children. |
|
45 | 45 | includes(:author, :attachments, {:board => :project}). |
|
46 | reorder("#{Message.table_name}.created_on ASC"). | |
|
46 | reorder("#{Message.table_name}.created_on ASC, #{Message.table_name}.id ASC"). | |
|
47 | 47 | limit(@reply_pages.per_page). |
|
48 | 48 | offset(@reply_pages.offset). |
|
49 |
a |
|
|
49 | to_a | |
|
50 | 50 | |
|
51 | 51 | @reply = Message.new(:subject => "RE: #{@message.subject}") |
|
52 | 52 | render :action => "show", :layout => false if request.xhr? |
@@ -53,8 +53,8 class MyController < ApplicationController | |||
|
53 | 53 | @user = User.current |
|
54 | 54 | @pref = @user.pref |
|
55 | 55 | if request.post? |
|
56 | @user.safe_attributes = params[:user] | |
|
57 | @user.pref.attributes = params[:pref] | |
|
56 | @user.safe_attributes = params[:user] if params[:user] | |
|
57 | @user.pref.attributes = params[:pref] if params[:pref] | |
|
58 | 58 | if @user.save |
|
59 | 59 | @user.pref.save |
|
60 | 60 | set_language_if_valid @user.language |
@@ -46,7 +46,7 class NewsController < ApplicationController | |||
|
46 | 46 | order("#{News.table_name}.created_on DESC"). |
|
47 | 47 | limit(@limit). |
|
48 | 48 | offset(@offset). |
|
49 |
a |
|
|
49 | to_a | |
|
50 | 50 | respond_to do |format| |
|
51 | 51 | format.html { |
|
52 | 52 | @news = News.new # for adding news inline |
@@ -20,7 +20,7 class ProjectEnumerationsController < ApplicationController | |||
|
20 | 20 | before_filter :authorize |
|
21 | 21 | |
|
22 | 22 | def update |
|
23 |
if |
|
|
23 | if params[:enumerations] | |
|
24 | 24 | Project.transaction do |
|
25 | 25 | params[:enumerations].each do |id, activity| |
|
26 | 26 | @project.update_or_create_time_entry_activity(id, activity) |
@@ -53,30 +53,30 class ProjectsController < ApplicationController | |||
|
53 | 53 | unless params[:closed] |
|
54 | 54 | scope = scope.active |
|
55 | 55 | end |
|
56 |
@projects = scope.visible.order('lft').a |
|
|
56 | @projects = scope.visible.order('lft').to_a | |
|
57 | 57 | } |
|
58 | 58 | format.api { |
|
59 | 59 | @offset, @limit = api_offset_and_limit |
|
60 | 60 | @project_count = Project.visible.count |
|
61 |
@projects = Project.visible.offset(@offset).limit(@limit).order('lft').a |
|
|
61 | @projects = Project.visible.offset(@offset).limit(@limit).order('lft').to_a | |
|
62 | 62 | } |
|
63 | 63 | format.atom { |
|
64 |
projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).a |
|
|
64 | projects = Project.visible.order('created_on DESC').limit(Setting.feeds_limit.to_i).to_a | |
|
65 | 65 | render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}") |
|
66 | 66 | } |
|
67 | 67 | end |
|
68 | 68 | end |
|
69 | 69 | |
|
70 | 70 | def new |
|
71 |
@issue_custom_fields = IssueCustomField.sorted.a |
|
|
72 |
@trackers = Tracker.sorted.a |
|
|
71 | @issue_custom_fields = IssueCustomField.sorted.to_a | |
|
72 | @trackers = Tracker.sorted.to_a | |
|
73 | 73 | @project = Project.new |
|
74 | 74 | @project.safe_attributes = params[:project] |
|
75 | 75 | end |
|
76 | 76 | |
|
77 | 77 | def create |
|
78 |
@issue_custom_fields = IssueCustomField.sorted.a |
|
|
79 |
@trackers = Tracker.sorted.a |
|
|
78 | @issue_custom_fields = IssueCustomField.sorted.to_a | |
|
79 | @trackers = Tracker.sorted.to_a | |
|
80 | 80 | @project = Project.new |
|
81 | 81 | @project.safe_attributes = params[:project] |
|
82 | 82 | |
@@ -109,8 +109,8 class ProjectsController < ApplicationController | |||
|
109 | 109 | end |
|
110 | 110 | |
|
111 | 111 | def copy |
|
112 |
@issue_custom_fields = IssueCustomField.sorted.a |
|
|
113 |
@trackers = Tracker.sorted.a |
|
|
112 | @issue_custom_fields = IssueCustomField.sorted.to_a | |
|
113 | @trackers = Tracker.sorted.to_a | |
|
114 | 114 | @source_project = Project.find(params[:id]) |
|
115 | 115 | if request.get? |
|
116 | 116 | @project = Project.copy_from(@source_project) |
@@ -145,8 +145,8 class ProjectsController < ApplicationController | |||
|
145 | 145 | end |
|
146 | 146 | |
|
147 | 147 | @users_by_role = @project.users_by_role |
|
148 |
@subprojects = @project.children.visible.a |
|
|
149 |
@news = @project.news.limit(5).includes(:author, :project).reorder("#{News.table_name}.created_on DESC").a |
|
|
148 | @subprojects = @project.children.visible.to_a | |
|
149 | @news = @project.news.limit(5).includes(:author, :project).reorder("#{News.table_name}.created_on DESC").to_a | |
|
150 | 150 | @trackers = @project.rolled_up_trackers |
|
151 | 151 | |
|
152 | 152 | cond = @project.project_condition(Setting.display_subprojects_issues?) |
@@ -167,10 +167,10 class ProjectsController < ApplicationController | |||
|
167 | 167 | end |
|
168 | 168 | |
|
169 | 169 | def settings |
|
170 |
@issue_custom_fields = IssueCustomField.sorted.a |
|
|
170 | @issue_custom_fields = IssueCustomField.sorted.to_a | |
|
171 | 171 | @issue_category ||= IssueCategory.new |
|
172 | 172 | @member ||= @project.members.new |
|
173 |
@trackers = Tracker.sorted.a |
|
|
173 | @trackers = Tracker.sorted.to_a | |
|
174 | 174 | @wiki ||= @project.wiki |
|
175 | 175 | end |
|
176 | 176 |
@@ -37,8 +37,9 class QueriesController < ApplicationController | |||
|
37 | 37 | order("#{Query.table_name}.name"). |
|
38 | 38 | limit(@limit). |
|
39 | 39 | offset(@offset). |
|
40 |
a |
|
|
40 | to_a | |
|
41 | 41 | respond_to do |format| |
|
42 | format.html {render_error :status => 406} | |
|
42 | 43 | format.api |
|
43 | 44 | end |
|
44 | 45 | end |
@@ -90,6 +90,6 class ReportsController < ApplicationController | |||
|
90 | 90 | private |
|
91 | 91 | |
|
92 | 92 | def find_issue_statuses |
|
93 |
@statuses = IssueStatus.sorted.a |
|
|
93 | @statuses = IssueStatus.sorted.to_a | |
|
94 | 94 | end |
|
95 | 95 | end |
@@ -69,7 +69,7 class RepositoriesController < ApplicationController | |||
|
69 | 69 | @repository.merge_extra_info(attrs[:attrs_extra]) |
|
70 | 70 | end |
|
71 | 71 | @repository.project = @project |
|
72 |
if |
|
|
72 | if @repository.save | |
|
73 | 73 | redirect_to settings_project_path(@project, :tab => 'repositories') |
|
74 | 74 | else |
|
75 | 75 | render :action => 'edit' |
@@ -94,7 +94,7 class RepositoriesController < ApplicationController | |||
|
94 | 94 | @committers = @repository.committers |
|
95 | 95 | @users = @project.users |
|
96 | 96 | additional_user_ids = @committers.collect(&:last).collect(&:to_i) - @users.collect(&:id) |
|
97 |
@users += User.where(:id => additional_user_ids).a |
|
|
97 | @users += User.where(:id => additional_user_ids).to_a unless additional_user_ids.empty? | |
|
98 | 98 | @users.compact! |
|
99 | 99 | @users.sort! |
|
100 | 100 | if request.post? && params[:committers].is_a?(Hash) |
@@ -145,7 +145,7 class RepositoriesController < ApplicationController | |||
|
145 | 145 | limit(@changeset_pages.per_page). |
|
146 | 146 | offset(@changeset_pages.offset). |
|
147 | 147 | includes(:user, :repository, :parents). |
|
148 |
a |
|
|
148 | to_a | |
|
149 | 149 | |
|
150 | 150 | respond_to do |format| |
|
151 | 151 | format.html { render :layout => false if request.xhr? } |
@@ -30,7 +30,7 class RolesController < ApplicationController | |||
|
30 | 30 | render :action => "index", :layout => false if request.xhr? |
|
31 | 31 | } |
|
32 | 32 | format.api { |
|
33 |
@roles = Role.givable.a |
|
|
33 | @roles = Role.givable.to_a | |
|
34 | 34 | } |
|
35 | 35 | end |
|
36 | 36 | end |
@@ -47,7 +47,7 class RolesController < ApplicationController | |||
|
47 | 47 | if params[:copy].present? && @copy_from = Role.find_by_id(params[:copy]) |
|
48 | 48 | @role.copy_from(@copy_from) |
|
49 | 49 | end |
|
50 |
@roles = Role.sorted.a |
|
|
50 | @roles = Role.sorted.to_a | |
|
51 | 51 | end |
|
52 | 52 | |
|
53 | 53 | def create |
@@ -60,7 +60,7 class RolesController < ApplicationController | |||
|
60 | 60 | flash[:notice] = l(:notice_successful_create) |
|
61 | 61 | redirect_to roles_path |
|
62 | 62 | else |
|
63 |
@roles = Role.sorted.a |
|
|
63 | @roles = Role.sorted.to_a | |
|
64 | 64 | render :action => 'new' |
|
65 | 65 | end |
|
66 | 66 | end |
@@ -69,7 +69,7 class RolesController < ApplicationController | |||
|
69 | 69 | end |
|
70 | 70 | |
|
71 | 71 | def update |
|
72 |
if |
|
|
72 | if @role.update_attributes(params[:role]) | |
|
73 | 73 | flash[:notice] = l(:notice_successful_update) |
|
74 | 74 | redirect_to roles_path |
|
75 | 75 | else |
@@ -86,7 +86,7 class RolesController < ApplicationController | |||
|
86 | 86 | end |
|
87 | 87 | |
|
88 | 88 | def permissions |
|
89 |
@roles = Role.sorted.a |
|
|
89 | @roles = Role.sorted.to_a | |
|
90 | 90 | @permissions = Redmine::AccessControl.permissions.select { |p| !p.public? } |
|
91 | 91 | if request.post? |
|
92 | 92 | @roles.each do |role| |
@@ -31,7 +31,7 class SearchController < ApplicationController | |||
|
31 | 31 | when 'my_projects' |
|
32 | 32 | User.current.memberships.collect(&:project) |
|
33 | 33 | when 'subprojects' |
|
34 |
@project ? (@project.self_and_descendants.active.a |
|
|
34 | @project ? (@project.self_and_descendants.active.to_a) : nil | |
|
35 | 35 | else |
|
36 | 36 | @project |
|
37 | 37 | end |
@@ -19,7 +19,8 class SysController < ActionController::Base | |||
|
19 | 19 | before_filter :check_enabled |
|
20 | 20 | |
|
21 | 21 | def projects |
|
22 | p = Project.active.has_module(:repository).order("#{Project.table_name}.identifier").preload(:repository).all | |
|
22 | p = Project.active.has_module(:repository). | |
|
23 | order("#{Project.table_name}.identifier").preload(:repository).to_a | |
|
23 | 24 | # extra_info attribute from repository breaks activeresource client |
|
24 | 25 | render :xml => p.to_xml( |
|
25 | 26 | :only => [:id, :identifier, :name, :is_public, :status], |
@@ -56,7 +57,7 class SysController < ActionController::Base | |||
|
56 | 57 | raise ActiveRecord::RecordNotFound unless project |
|
57 | 58 | projects << project |
|
58 | 59 | else |
|
59 |
projects = scope.a |
|
|
60 | projects = scope.to_a | |
|
60 | 61 | end |
|
61 | 62 | projects.each do |project| |
|
62 | 63 | project.repositories.each do |repository| |
@@ -52,7 +52,7 class TimelogController < ApplicationController | |||
|
52 | 52 | format.html { |
|
53 | 53 | @entry_count = scope.count |
|
54 | 54 | @entry_pages = Paginator.new @entry_count, per_page_option, params['page'] |
|
55 |
@entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).a |
|
|
55 | @entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).to_a | |
|
56 | 56 | @total_hours = scope.sum(:hours).to_f |
|
57 | 57 | |
|
58 | 58 | render :layout => !request.xhr? |
@@ -60,15 +60,15 class TimelogController < ApplicationController | |||
|
60 | 60 | format.api { |
|
61 | 61 | @entry_count = scope.count |
|
62 | 62 | @offset, @limit = api_offset_and_limit |
|
63 |
@entries = scope.offset(@offset).limit(@limit).preload(:custom_values => :custom_field).a |
|
|
63 | @entries = scope.offset(@offset).limit(@limit).preload(:custom_values => :custom_field).to_a | |
|
64 | 64 | } |
|
65 | 65 | format.atom { |
|
66 |
entries = scope.limit(Setting.feeds_limit.to_i).reorder("#{TimeEntry.table_name}.created_on DESC").a |
|
|
66 | entries = scope.limit(Setting.feeds_limit.to_i).reorder("#{TimeEntry.table_name}.created_on DESC").to_a | |
|
67 | 67 | render_feed(entries, :title => l(:label_spent_time)) |
|
68 | 68 | } |
|
69 | 69 | format.csv { |
|
70 | 70 | # Export all entries |
|
71 |
@entries = scope.a |
|
|
71 | @entries = scope.to_a | |
|
72 | 72 | send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv') |
|
73 | 73 | } |
|
74 | 74 | end |
@@ -232,7 +232,7 private | |||
|
232 | 232 | end |
|
233 | 233 | |
|
234 | 234 | def find_time_entries |
|
235 |
@time_entries = TimeEntry.where(:id => params[:id] || params[:ids]).a |
|
|
235 | @time_entries = TimeEntry.where(:id => params[:id] || params[:ids]).to_a | |
|
236 | 236 | raise ActiveRecord::RecordNotFound if @time_entries.empty? |
|
237 | 237 | @projects = @time_entries.collect(&:project).compact.uniq |
|
238 | 238 | @project = @projects.first if @projects.size == 1 |
@@ -29,14 +29,14 class TrackersController < ApplicationController | |||
|
29 | 29 | render :action => "index", :layout => false if request.xhr? |
|
30 | 30 | } |
|
31 | 31 | format.api { |
|
32 |
@trackers = Tracker.sorted.a |
|
|
32 | @trackers = Tracker.sorted.to_a | |
|
33 | 33 | } |
|
34 | 34 | end |
|
35 | 35 | end |
|
36 | 36 | |
|
37 | 37 | def new |
|
38 | 38 | @tracker ||= Tracker.new(params[:tracker]) |
|
39 |
@trackers = Tracker.sorted.a |
|
|
39 | @trackers = Tracker.sorted.to_a | |
|
40 | 40 | @projects = Project.all |
|
41 | 41 | end |
|
42 | 42 | |
@@ -95,7 +95,7 class TrackersController < ApplicationController | |||
|
95 | 95 | redirect_to fields_trackers_path |
|
96 | 96 | return |
|
97 | 97 | end |
|
98 |
@trackers = Tracker.sorted.a |
|
|
98 | @trackers = Tracker.sorted.to_a | |
|
99 | 99 | @custom_fields = IssueCustomField.all.sort |
|
100 | 100 | end |
|
101 | 101 | end |
@@ -47,7 +47,7 class UsersController < ApplicationController | |||
|
47 | 47 | @user_count = scope.count |
|
48 | 48 | @user_pages = Paginator.new @user_count, @limit, params['page'] |
|
49 | 49 | @offset ||= @user_pages.offset |
|
50 |
@users = scope.order(sort_clause).limit(@limit).offset(@offset).a |
|
|
50 | @users = scope.order(sort_clause).limit(@limit).offset(@offset).to_a | |
|
51 | 51 | |
|
52 | 52 | respond_to do |format| |
|
53 | 53 | format.html { |
@@ -60,7 +60,7 class UsersController < ApplicationController | |||
|
60 | 60 | |
|
61 | 61 | def show |
|
62 | 62 | # show projects based on current user visibility |
|
63 |
@memberships = @user.memberships.where(Project.visible_condition(User.current)).a |
|
|
63 | @memberships = @user.memberships.where(Project.visible_condition(User.current)).to_a | |
|
64 | 64 | |
|
65 | 65 | events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10) |
|
66 | 66 | @events_by_day = events.group_by(&:event_date) |
@@ -90,7 +90,7 class UsersController < ApplicationController | |||
|
90 | 90 | @user.admin = params[:user][:admin] || false |
|
91 | 91 | @user.login = params[:user][:login] |
|
92 | 92 | @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id |
|
93 | @user.pref.attributes = params[:pref] | |
|
93 | @user.pref.attributes = params[:pref] if params[:pref] | |
|
94 | 94 | |
|
95 | 95 | if @user.save |
|
96 | 96 | Mailer.account_information(@user, @user.password).deliver if params[:send_information] |
@@ -134,7 +134,7 class UsersController < ApplicationController | |||
|
134 | 134 | # Was the account actived ? (do it before User#save clears the change) |
|
135 | 135 | was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE]) |
|
136 | 136 | # TODO: Similar to My#account |
|
137 | @user.pref.attributes = params[:pref] | |
|
137 | @user.pref.attributes = params[:pref] if params[:pref] | |
|
138 | 138 | |
|
139 | 139 | if @user.save |
|
140 | 140 | @user.pref.save |
@@ -31,7 +31,7 class VersionsController < ApplicationController | |||
|
31 | 31 | def index |
|
32 | 32 | respond_to do |format| |
|
33 | 33 | format.html { |
|
34 |
@trackers = @project.trackers.sorted.a |
|
|
34 | @trackers = @project.trackers.sorted.to_a | |
|
35 | 35 | retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?}) |
|
36 | 36 | @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1') |
|
37 | 37 | project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id] |
@@ -56,7 +56,7 class VersionsController < ApplicationController | |||
|
56 | 56 | @versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?} |
|
57 | 57 | } |
|
58 | 58 | format.api { |
|
59 |
@versions = @project.shared_versions.a |
|
|
59 | @versions = @project.shared_versions.to_a | |
|
60 | 60 | } |
|
61 | 61 | end |
|
62 | 62 | end |
@@ -67,7 +67,7 class VersionsController < ApplicationController | |||
|
67 | 67 | @issues = @version.fixed_issues.visible. |
|
68 | 68 | includes(:status, :tracker, :priority). |
|
69 | 69 | reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id"). |
|
70 |
a |
|
|
70 | to_a | |
|
71 | 71 | } |
|
72 | 72 | format.api |
|
73 | 73 | end |
@@ -117,7 +117,7 class VersionsController < ApplicationController | |||
|
117 | 117 | end |
|
118 | 118 | |
|
119 | 119 | def update |
|
120 |
if |
|
|
120 | if params[:version] | |
|
121 | 121 | attributes = params[:version].dup |
|
122 | 122 | attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing']) |
|
123 | 123 | @version.safe_attributes = attributes |
@@ -53,7 +53,7 class WatchersController < ApplicationController | |||
|
53 | 53 | def append |
|
54 | 54 | if params[:watcher].is_a?(Hash) |
|
55 | 55 | user_ids = params[:watcher][:user_ids] || [params[:watcher][:user_id]] |
|
56 |
@users = User.active.where(:id => user_ids).a |
|
|
56 | @users = User.active.where(:id => user_ids).to_a | |
|
57 | 57 | end |
|
58 | 58 | if @users.blank? |
|
59 | 59 | render :nothing => true |
@@ -92,7 +92,7 class WatchersController < ApplicationController | |||
|
92 | 92 | def find_watchables |
|
93 | 93 | klass = Object.const_get(params[:object_type].camelcase) rescue nil |
|
94 | 94 | if klass && klass.respond_to?('watched_by') |
|
95 |
@watchables = klass.where(:id => Array.wrap(params[:object_id])).a |
|
|
95 | @watchables = klass.where(:id => Array.wrap(params[:object_id])).to_a | |
|
96 | 96 | raise Unauthorized if @watchables.any? {|w| |
|
97 | 97 | if w.respond_to?(:visible?) |
|
98 | 98 | !w.visible? |
@@ -219,7 +219,7 class WikiController < ApplicationController | |||
|
219 | 219 | reorder('version DESC'). |
|
220 | 220 | limit(@version_pages.per_page + 1). |
|
221 | 221 | offset(@version_pages.offset). |
|
222 |
a |
|
|
222 | to_a | |
|
223 | 223 | |
|
224 | 224 | render :layout => false if request.xhr? |
|
225 | 225 | end |
@@ -280,7 +280,7 class WikiController < ApplicationController | |||
|
280 | 280 | @pages = @wiki.pages. |
|
281 | 281 | order('title'). |
|
282 | 282 | includes([:content, {:attachments => :author}]). |
|
283 |
a |
|
|
283 | to_a | |
|
284 | 284 | respond_to do |format| |
|
285 | 285 | format.html { |
|
286 | 286 | export = render_to_string :action => 'export_multiple', :layout => false |
@@ -327,7 +327,7 private | |||
|
327 | 327 | def find_existing_or_new_page |
|
328 | 328 | @page = @wiki.find_or_new_page(params[:id]) |
|
329 | 329 | if @wiki.page_found_with_redirect? |
|
330 |
redirect_to |
|
|
330 | redirect_to_page @page | |
|
331 | 331 | end |
|
332 | 332 | end |
|
333 | 333 | |
@@ -339,10 +339,14 private | |||
|
339 | 339 | return |
|
340 | 340 | end |
|
341 | 341 | if @wiki.page_found_with_redirect? |
|
342 |
redirect_to |
|
|
342 | redirect_to_page @page | |
|
343 | 343 | end |
|
344 | 344 | end |
|
345 | 345 | |
|
346 | def redirect_to_page(page) | |
|
347 | redirect_to :action => action_name, :project_id => page.wiki.project, :id => page.title | |
|
348 | end | |
|
349 | ||
|
346 | 350 | # Returns true if the current user is allowed to edit the page, otherwise false |
|
347 | 351 | def editable?(page = @page) |
|
348 | 352 | page.editable_by?(User.current) |
@@ -360,6 +364,6 private | |||
|
360 | 364 | reorder("#{WikiPage.table_name}.title"). |
|
361 | 365 | includes(:wiki => :project). |
|
362 | 366 | includes(:parent). |
|
363 |
a |
|
|
367 | to_a | |
|
364 | 368 | end |
|
365 | 369 | end |
@@ -86,9 +86,9 class WorkflowsController < ApplicationController | |||
|
86 | 86 | @source_role = Role.find_by_id(params[:source_role_id].to_i) |
|
87 | 87 | end |
|
88 | 88 | @target_trackers = params[:target_tracker_ids].blank? ? |
|
89 |
nil : Tracker.where(:id => params[:target_tracker_ids]).a |
|
|
89 | nil : Tracker.where(:id => params[:target_tracker_ids]).to_a | |
|
90 | 90 | @target_roles = params[:target_role_ids].blank? ? |
|
91 |
nil : Role.where(:id => params[:target_role_ids]).a |
|
|
91 | nil : Role.where(:id => params[:target_role_ids]).to_a | |
|
92 | 92 | if request.post? |
|
93 | 93 | if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?) |
|
94 | 94 | flash.now[:error] = l(:error_workflow_copy_source) |
@@ -113,9 +113,9 class WorkflowsController < ApplicationController | |||
|
113 | 113 | def find_roles |
|
114 | 114 | ids = Array.wrap(params[:role_id]) |
|
115 | 115 | if ids == ['all'] |
|
116 |
@roles = Role.sorted.a |
|
|
116 | @roles = Role.sorted.to_a | |
|
117 | 117 | elsif ids.present? |
|
118 |
@roles = Role.where(:id => ids).a |
|
|
118 | @roles = Role.where(:id => ids).to_a | |
|
119 | 119 | end |
|
120 | 120 | @roles = nil if @roles.blank? |
|
121 | 121 | end |
@@ -123,9 +123,9 class WorkflowsController < ApplicationController | |||
|
123 | 123 | def find_trackers |
|
124 | 124 | ids = Array.wrap(params[:tracker_id]) |
|
125 | 125 | if ids == ['all'] |
|
126 |
@trackers = Tracker.sorted.a |
|
|
126 | @trackers = Tracker.sorted.to_a | |
|
127 | 127 | elsif ids.present? |
|
128 |
@trackers = Tracker.where(:id => ids).a |
|
|
128 | @trackers = Tracker.where(:id => ids).to_a | |
|
129 | 129 | end |
|
130 | 130 | @trackers = nil if @trackers.blank? |
|
131 | 131 | end |
@@ -135,6 +135,6 class WorkflowsController < ApplicationController | |||
|
135 | 135 | if @trackers && @used_statuses_only |
|
136 | 136 | @statuses = @trackers.map(&:issue_statuses).flatten.uniq.sort.presence |
|
137 | 137 | end |
|
138 |
@statuses ||= IssueStatus.sorted.a |
|
|
138 | @statuses ||= IssueStatus.sorted.to_a | |
|
139 | 139 | end |
|
140 | 140 | end |
@@ -138,9 +138,7 module ApplicationHelper | |||
|
138 | 138 | if project.archived? |
|
139 | 139 | h(project.name) |
|
140 | 140 | elsif options.key?(:action) |
|
141 | ActiveSupport::Deprecation.warn "#link_to_project with :action option is deprecated and will be removed in Redmine 3.0." | |
|
142 | url = {:controller => 'projects', :action => 'show', :id => project}.merge(options) | |
|
143 | link_to project.name, url, html_options | |
|
141 | raise "#link_to_project no longer accepts :action option in Redmine 3.0" | |
|
144 | 142 | else |
|
145 | 143 | link_to project.name, project_path(project, options), html_options |
|
146 | 144 | end |
@@ -157,13 +155,6 module ApplicationHelper | |||
|
157 | 155 | end |
|
158 | 156 | end |
|
159 | 157 | |
|
160 | # Generates a link to a version | |
|
161 | def link_to_version(version, options = {}) | |
|
162 | return '' unless version && version.is_a?(Version) | |
|
163 | options = {:title => format_date(version.effective_date)}.merge(options) | |
|
164 | link_to_if version.visible?, format_version_name(version), version_path(version), options | |
|
165 | end | |
|
166 | ||
|
167 | 158 | # Helper that formats object for html or text rendering |
|
168 | 159 | def format_object(object, html=true, &block) |
|
169 | 160 | if block_given? |
@@ -185,7 +176,7 module ApplicationHelper | |||
|
185 | 176 | when 'Project' |
|
186 | 177 | html ? link_to_project(object) : object.to_s |
|
187 | 178 | when 'Version' |
|
188 |
html ? link_to |
|
|
179 | html ? link_to(object.name, version_path(object)) : object.to_s | |
|
189 | 180 | when 'TrueClass' |
|
190 | 181 | l(:general_text_Yes) |
|
191 | 182 | when 'FalseClass' |
@@ -247,7 +238,7 module ApplicationHelper | |||
|
247 | 238 | end |
|
248 | 239 | |
|
249 | 240 | def format_version_name(version) |
|
250 |
if |
|
|
241 | if version.project == @project | |
|
251 | 242 | h(version) |
|
252 | 243 | else |
|
253 | 244 | h("#{version.project} - #{version}") |
@@ -502,7 +493,7 module ApplicationHelper | |||
|
502 | 493 | h(Setting.app_title) |
|
503 | 494 | else |
|
504 | 495 | b = [] |
|
505 |
ancestors = (@project.root? ? [] : @project.ancestors.visible.a |
|
|
496 | ancestors = (@project.root? ? [] : @project.ancestors.visible.to_a) | |
|
506 | 497 | if ancestors.any? |
|
507 | 498 | root = ancestors.shift |
|
508 | 499 | b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') |
@@ -1217,7 +1208,7 module ApplicationHelper | |||
|
1217 | 1208 | source |
|
1218 | 1209 | end |
|
1219 | 1210 | end |
|
1220 | super sources, options | |
|
1211 | super *sources, options | |
|
1221 | 1212 | end |
|
1222 | 1213 | |
|
1223 | 1214 | # Overrides Rails' image_tag with themes and plugins support. |
@@ -1250,7 +1241,7 module ApplicationHelper | |||
|
1250 | 1241 | end |
|
1251 | 1242 | end |
|
1252 | 1243 | end |
|
1253 | super sources, options | |
|
1244 | super *sources, options | |
|
1254 | 1245 | end |
|
1255 | 1246 | |
|
1256 | 1247 | # TODO: remove this in 2.5.0 |
@@ -1288,12 +1279,7 module ApplicationHelper | |||
|
1288 | 1279 | end |
|
1289 | 1280 | |
|
1290 | 1281 | def sanitize_anchor_name(anchor) |
|
1291 | if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' | |
|
1292 | anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | |
|
1293 | else | |
|
1294 | # TODO: remove when ruby1.8 is no longer supported | |
|
1295 | anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | |
|
1296 | end | |
|
1282 | anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | |
|
1297 | 1283 | end |
|
1298 | 1284 | |
|
1299 | 1285 | # Returns the javascript tags that are included in the html layout head |
@@ -30,7 +30,7 module GroupsHelper | |||
|
30 | 30 | scope = User.active.sorted.not_in_group(group).like(params[:q]) |
|
31 | 31 | principal_count = scope.count |
|
32 | 32 | principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page'] |
|
33 |
principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).a |
|
|
33 | principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).to_a | |
|
34 | 34 | |
|
35 | 35 | s = content_tag('div', principals_check_box_tags('user_ids[]', principals), :id => 'principals') |
|
36 | 36 |
@@ -63,7 +63,7 module IssuesHelper | |||
|
63 | 63 | |
|
64 | 64 | def render_issue_subject_with_tree(issue) |
|
65 | 65 | s = '' |
|
66 |
ancestors = issue.root? ? [] : issue.ancestors.visible.a |
|
|
66 | ancestors = issue.root? ? [] : issue.ancestors.visible.to_a | |
|
67 | 67 | ancestors.each do |ancestor| |
|
68 | 68 | s << '<div>' + content_tag('p', link_to_issue(ancestor, :project => (issue.project_id != ancestor.project_id))) |
|
69 | 69 | end |
@@ -204,7 +204,7 module IssuesHelper | |||
|
204 | 204 | order("#{Query.table_name}.name ASC"). |
|
205 | 205 | # Project specific queries and global queries |
|
206 | 206 | where(@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id]). |
|
207 |
a |
|
|
207 | to_a | |
|
208 | 208 | end |
|
209 | 209 | @sidebar_queries |
|
210 | 210 | end |
@@ -408,7 +408,7 module IssuesHelper | |||
|
408 | 408 | if association |
|
409 | 409 | record = association.class_name.constantize.find_by_id(id) |
|
410 | 410 | if record |
|
411 |
record.name.force_encoding('UTF-8') |
|
|
411 | record.name.force_encoding('UTF-8') | |
|
412 | 412 | return record.name |
|
413 | 413 | end |
|
414 | 414 | end |
@@ -22,7 +22,7 module MembersHelper | |||
|
22 | 22 | scope = Principal.active.sorted.not_member_of(project).like(params[:q]) |
|
23 | 23 | principal_count = scope.count |
|
24 | 24 | principal_pages = Redmine::Pagination::Paginator.new principal_count, 100, params['page'] |
|
25 |
principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).a |
|
|
25 | principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).to_a | |
|
26 | 26 | |
|
27 | 27 | s = content_tag('div', principals_check_box_tags('membership[user_ids][]', principals), :id => 'principals') |
|
28 | 28 |
@@ -23,11 +23,12 module MyHelper | |||
|
23 | 23 | where(:project_id => User.current.projects.map(&:id)). |
|
24 | 24 | where("(start_date>=? and start_date<=?) or (due_date>=? and due_date<=?)", startdt, enddt, startdt, enddt). |
|
25 | 25 | includes(:project, :tracker, :priority, :assigned_to). |
|
26 | all | |
|
26 | references(:project, :tracker, :priority, :assigned_to). | |
|
27 | to_a | |
|
27 | 28 | end |
|
28 | 29 | |
|
29 | 30 | def documents_items |
|
30 |
Document.visible.order("#{Document.table_name}.created_on DESC").limit(10).a |
|
|
31 | Document.visible.order("#{Document.table_name}.created_on DESC").limit(10).to_a | |
|
31 | 32 | end |
|
32 | 33 | |
|
33 | 34 | def issuesassignedtome_items |
@@ -35,8 +36,9 module MyHelper | |||
|
35 | 36 | where(:assigned_to_id => ([User.current.id] + User.current.group_ids)). |
|
36 | 37 | limit(10). |
|
37 | 38 | includes(:status, :project, :tracker, :priority). |
|
39 | references(:status, :project, :tracker, :priority). | |
|
38 | 40 | order("#{IssuePriority.table_name}.position DESC, #{Issue.table_name}.updated_on DESC"). |
|
39 |
a |
|
|
41 | to_a | |
|
40 | 42 | end |
|
41 | 43 | |
|
42 | 44 | def issuesreportedbyme_items |
@@ -44,12 +46,13 module MyHelper | |||
|
44 | 46 | where(:author_id => User.current.id). |
|
45 | 47 | limit(10). |
|
46 | 48 | includes(:status, :project, :tracker). |
|
49 | references(:status, :project, :tracker). | |
|
47 | 50 | order("#{Issue.table_name}.updated_on DESC"). |
|
48 |
a |
|
|
51 | to_a | |
|
49 | 52 | end |
|
50 | 53 | |
|
51 | 54 | def issueswatched_items |
|
52 |
Issue.visible.on_active_project.watched_by(User.current.id).recently_updated.limit(10).a |
|
|
55 | Issue.visible.on_active_project.watched_by(User.current.id).recently_updated.limit(10).to_a | |
|
53 | 56 | end |
|
54 | 57 | |
|
55 | 58 | def news_items |
@@ -57,15 +60,17 module MyHelper | |||
|
57 | 60 | where(:project_id => User.current.projects.map(&:id)). |
|
58 | 61 | limit(10). |
|
59 | 62 | includes(:project, :author). |
|
63 | references(:project, :author). | |
|
60 | 64 | order("#{News.table_name}.created_on DESC"). |
|
61 |
a |
|
|
65 | to_a | |
|
62 | 66 | end |
|
63 | 67 | |
|
64 | 68 | def timelog_items |
|
65 | 69 | TimeEntry. |
|
66 | 70 | where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", User.current.id, Date.today - 6, Date.today). |
|
67 |
in |
|
|
71 | joins(:activity, :project, {:issue => [:tracker, :status]}). | |
|
72 | references(:activity, :project, {:issue => [:tracker, :status]}). | |
|
68 | 73 | order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC"). |
|
69 |
a |
|
|
74 | to_a | |
|
70 | 75 | end |
|
71 | 76 | end |
@@ -18,6 +18,11 | |||
|
18 | 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | 19 | |
|
20 | 20 | module ProjectsHelper |
|
21 | def link_to_version(version, options = {}) | |
|
22 | return '' unless version && version.is_a?(Version) | |
|
23 | link_to_if version.visible?, format_version_name(version), version_path(version), options | |
|
24 | end | |
|
25 | ||
|
21 | 26 | def project_settings_tabs |
|
22 | 27 | tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural}, |
|
23 | 28 | {:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural}, |
@@ -143,7 +143,7 module QueriesHelper | |||
|
143 | 143 | end |
|
144 | 144 | end |
|
145 | 145 | |
|
146 |
export = |
|
|
146 | export = CSV.generate(:col_sep => l(:general_csv_separator)) do |csv| | |
|
147 | 147 | # csv header fields |
|
148 | 148 | csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(c.caption.to_s, encoding) } |
|
149 | 149 | # csv lines |
@@ -29,7 +29,6 module SearchHelper | |||
|
29 | 29 | result << '...' |
|
30 | 30 | break |
|
31 | 31 | end |
|
32 | words = words.mb_chars | |
|
33 | 32 | if i.even? |
|
34 | 33 | result << h(words.length > 100 ? "#{words.slice(0..44)} ... #{words.slice(-45..-1)}" : words) |
|
35 | 34 | else |
@@ -84,7 +84,8 module SortHelper | |||
|
84 | 84 | def to_sql |
|
85 | 85 | sql = @criteria.collect do |k,o| |
|
86 | 86 | if s = @available_criteria[k] |
|
87 | (o ? s.to_a : s.to_a.collect {|c| append_desc(c)}) | |
|
87 | s = [s] unless s.is_a?(Array) | |
|
88 | (o ? s : s.collect {|c| append_desc(c)}) | |
|
88 | 89 | end |
|
89 | 90 | end.flatten.compact |
|
90 | 91 | sql.blank? ? nil : sql |
@@ -105,7 +105,7 module TimelogHelper | |||
|
105 | 105 | |
|
106 | 106 | def report_to_csv(report) |
|
107 | 107 | decimal_separator = l(:general_csv_decimal_separator) |
|
108 |
export = |
|
|
108 | export = CSV.generate(:col_sep => l(:general_csv_separator)) do |csv| | |
|
109 | 109 | # Column headers |
|
110 | 110 | headers = report.criteria.collect {|criteria| l(report.available_criteria[criteria][:label]) } |
|
111 | 111 | headers += report.periods |
@@ -27,6 +27,7 class Attachment < ActiveRecord::Base | |||
|
27 | 27 | validates_length_of :disk_filename, :maximum => 255 |
|
28 | 28 | validates_length_of :description, :maximum => 255 |
|
29 | 29 | validate :validate_max_file_size |
|
30 | attr_protected :id | |
|
30 | 31 | |
|
31 | 32 | acts_as_event :title => :filename, |
|
32 | 33 | :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id, :filename => o.filename}} |
@@ -34,16 +35,16 class Attachment < ActiveRecord::Base | |||
|
34 | 35 | acts_as_activity_provider :type => 'files', |
|
35 | 36 | :permission => :view_files, |
|
36 | 37 | :author_key => :author_id, |
|
37 |
: |
|
|
38 |
|
|
|
39 |
|
|
|
38 | :scope => select("#{Attachment.table_name}.*"). | |
|
39 | joins("LEFT JOIN #{Version.table_name} ON #{Attachment.table_name}.container_type='Version' AND #{Version.table_name}.id = #{Attachment.table_name}.container_id " + | |
|
40 | "LEFT JOIN #{Project.table_name} ON #{Version.table_name}.project_id = #{Project.table_name}.id OR ( #{Attachment.table_name}.container_type='Project' AND #{Attachment.table_name}.container_id = #{Project.table_name}.id )") | |
|
40 | 41 | |
|
41 | 42 | acts_as_activity_provider :type => 'documents', |
|
42 | 43 | :permission => :view_documents, |
|
43 | 44 | :author_key => :author_id, |
|
44 |
: |
|
|
45 |
|
|
|
46 |
|
|
|
45 | :scope => select("#{Attachment.table_name}.*"). | |
|
46 | joins("LEFT JOIN #{Document.table_name} ON #{Attachment.table_name}.container_type='Document' AND #{Document.table_name}.id = #{Attachment.table_name}.container_id " + | |
|
47 | "LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id") | |
|
47 | 48 | |
|
48 | 49 | cattr_accessor :storage_path |
|
49 | 50 | @@storage_path = Redmine::Configuration['attachments_storage_path'] || File.join(Rails.root, "files") |
@@ -74,7 +75,7 class Attachment < ActiveRecord::Base | |||
|
74 | 75 | if @temp_file.size > 0 |
|
75 | 76 | if @temp_file.respond_to?(:original_filename) |
|
76 | 77 | self.filename = @temp_file.original_filename |
|
77 |
self.filename.force_encoding("UTF-8") |
|
|
78 | self.filename.force_encoding("UTF-8") | |
|
78 | 79 | end |
|
79 | 80 | if @temp_file.respond_to?(:content_type) |
|
80 | 81 | self.content_type = @temp_file.content_type.to_s.chomp |
@@ -29,6 +29,7 class AuthSource < ActiveRecord::Base | |||
|
29 | 29 | validates_presence_of :name |
|
30 | 30 | validates_uniqueness_of :name |
|
31 | 31 | validates_length_of :name, :maximum => 60 |
|
32 | attr_protected :id | |
|
32 | 33 | |
|
33 | 34 | def authenticate(login, password) |
|
34 | 35 | end |
@@ -18,8 +18,8 | |||
|
18 | 18 | class Board < ActiveRecord::Base |
|
19 | 19 | include Redmine::SafeAttributes |
|
20 | 20 | belongs_to :project |
|
21 |
has_many :topics, :class_name => 'Message' |
|
|
22 |
has_many :messages, :dependent => :destroy |
|
|
21 | has_many :topics, lambda {where("#{Message.table_name}.parent_id IS NULL").order("#{Message.table_name}.created_on DESC")}, :class_name => 'Message' | |
|
22 | has_many :messages, lambda {order("#{Message.table_name}.created_on DESC")}, :dependent => :destroy | |
|
23 | 23 | belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id |
|
24 | 24 | acts_as_tree :dependent => :nullify |
|
25 | 25 | acts_as_list :scope => '(project_id = #{project_id} AND parent_id #{parent_id ? "= #{parent_id}" : "IS NULL"})' |
@@ -29,9 +29,12 class Board < ActiveRecord::Base | |||
|
29 | 29 | validates_length_of :name, :maximum => 30 |
|
30 | 30 | validates_length_of :description, :maximum => 255 |
|
31 | 31 | validate :validate_board |
|
32 | attr_protected :id | |
|
32 | 33 | |
|
33 | 34 | scope :visible, lambda {|*args| |
|
34 | includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args)) | |
|
35 | joins(:project). | |
|
36 | references(:project). | |
|
37 | where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args)) | |
|
35 | 38 | } |
|
36 | 39 | |
|
37 | 40 | safe_attributes 'name', 'description', 'parent_id', 'move_to' |
@@ -21,6 +21,7 class Change < ActiveRecord::Base | |||
|
21 | 21 | validates_presence_of :changeset_id, :action, :path |
|
22 | 22 | before_save :init_path |
|
23 | 23 | before_validation :replace_invalid_utf8_of_path |
|
24 | attr_protected :id | |
|
24 | 25 | |
|
25 | 26 | def relative_path |
|
26 | 27 | changeset.repository.relative_path(path) |
@@ -35,20 +35,23 class Changeset < ActiveRecord::Base | |||
|
35 | 35 | :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :repository_id => o.repository.identifier_param, :rev => o.identifier}} |
|
36 | 36 | |
|
37 | 37 | acts_as_searchable :columns => 'comments', |
|
38 |
: |
|
|
38 | :scope => preload(:repository => :project), | |
|
39 | 39 | :project_key => "#{Repository.table_name}.project_id", |
|
40 | 40 | :date_column => 'committed_on' |
|
41 | 41 | |
|
42 | 42 | acts_as_activity_provider :timestamp => "#{table_name}.committed_on", |
|
43 | 43 | :author_key => :user_id, |
|
44 |
: |
|
|
44 | :scope => preload(:user, {:repository => :project}) | |
|
45 | 45 | |
|
46 | 46 | validates_presence_of :repository_id, :revision, :committed_on, :commit_date |
|
47 | 47 | validates_uniqueness_of :revision, :scope => :repository_id |
|
48 | 48 | validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true |
|
49 | attr_protected :id | |
|
49 | 50 | |
|
50 | 51 | scope :visible, lambda {|*args| |
|
51 | includes(:repository => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args)) | |
|
52 | joins(:repository => :project). | |
|
53 | references(:repository => :project). | |
|
54 | where(Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args)) | |
|
52 | 55 | } |
|
53 | 56 | |
|
54 | 57 | after_create :scan_for_issues |
@@ -21,6 +21,7 class Comment < ActiveRecord::Base | |||
|
21 | 21 | belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' |
|
22 | 22 | |
|
23 | 23 | validates_presence_of :commented, :author, :comments |
|
24 | attr_protected :id | |
|
24 | 25 | |
|
25 | 26 | after_create :send_notification |
|
26 | 27 |
@@ -29,6 +29,7 class CustomField < ActiveRecord::Base | |||
|
29 | 29 | validates_length_of :name, :maximum => 30 |
|
30 | 30 | validates_inclusion_of :field_format, :in => Proc.new { Redmine::FieldFormat.available_formats } |
|
31 | 31 | validate :validate_custom_field |
|
32 | attr_protected :id | |
|
32 | 33 | |
|
33 | 34 | before_validation :set_searchable |
|
34 | 35 | before_save do |field| |
@@ -117,7 +118,7 class CustomField < ActiveRecord::Base | |||
|
117 | 118 | values = read_attribute(:possible_values) |
|
118 | 119 | if values.is_a?(Array) |
|
119 | 120 | values.each do |value| |
|
120 |
value.force_encoding('UTF-8') |
|
|
121 | value.force_encoding('UTF-8') | |
|
121 | 122 | end |
|
122 | 123 | values |
|
123 | 124 | else |
@@ -218,7 +219,7 class CustomField < ActiveRecord::Base | |||
|
218 | 219 | |
|
219 | 220 | # to move in project_custom_field |
|
220 | 221 | def self.for_all |
|
221 |
where(:is_for_all => true).order('position').a |
|
|
222 | where(:is_for_all => true).order('position').to_a | |
|
222 | 223 | end |
|
223 | 224 | |
|
224 | 225 | def type_name |
@@ -18,6 +18,7 | |||
|
18 | 18 | class CustomValue < ActiveRecord::Base |
|
19 | 19 | belongs_to :custom_field |
|
20 | 20 | belongs_to :customized, :polymorphic => true |
|
21 | attr_protected :id | |
|
21 | 22 | |
|
22 | 23 | def initialize(attributes=nil, *args) |
|
23 | 24 | super |
@@ -21,19 +21,23 class Document < ActiveRecord::Base | |||
|
21 | 21 | belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id" |
|
22 | 22 | acts_as_attachable :delete_permission => :delete_documents |
|
23 | 23 | |
|
24 |
acts_as_searchable :columns => ['title', "#{table_name}.description"], |
|
|
24 | acts_as_searchable :columns => ['title', "#{table_name}.description"], | |
|
25 | :scope => preload(:project) | |
|
25 | 26 | acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"}, |
|
26 | 27 | :author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) }, |
|
27 | 28 | :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}} |
|
28 |
acts_as_activity_provider : |
|
|
29 | acts_as_activity_provider :scope => preload(:project) | |
|
29 | 30 | |
|
30 | 31 | validates_presence_of :project, :title, :category |
|
31 | 32 | validates_length_of :title, :maximum => 60 |
|
33 | attr_protected :id | |
|
32 | 34 | |
|
33 | 35 | after_create :send_notification |
|
34 | 36 | |
|
35 | 37 | scope :visible, lambda {|*args| |
|
36 | includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args)) | |
|
38 | joins(:project). | |
|
39 | references(:project). | |
|
40 | where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args)) | |
|
37 | 41 | } |
|
38 | 42 | |
|
39 | 43 | safe_attributes 'category_id', 'title', 'description' |
@@ -21,6 +21,7 class EnabledModule < ActiveRecord::Base | |||
|
21 | 21 | |
|
22 | 22 | validates_presence_of :name |
|
23 | 23 | validates_uniqueness_of :name, :scope => :project_id |
|
24 | attr_protected :id | |
|
24 | 25 | |
|
25 | 26 | after_create :module_enabled |
|
26 | 27 |
@@ -18,7 +18,7 | |||
|
18 | 18 | class Enumeration < ActiveRecord::Base |
|
19 | 19 | include Redmine::SubclassFactory |
|
20 | 20 | |
|
21 |
default_scope |
|
|
21 | default_scope lambda {order("#{Enumeration.table_name}.position ASC")} | |
|
22 | 22 | |
|
23 | 23 | belongs_to :project |
|
24 | 24 |
@@ -28,6 +28,7 class Group < Principal | |||
|
28 | 28 | validates_presence_of :lastname |
|
29 | 29 | validates_uniqueness_of :lastname, :case_sensitive => false |
|
30 | 30 | validates_length_of :lastname, :maximum => 255 |
|
31 | attr_protected :id | |
|
31 | 32 | |
|
32 | 33 | before_destroy :remove_references_before_destroy |
|
33 | 34 | |
@@ -81,7 +82,8 class Group < Principal | |||
|
81 | 82 | def user_removed(user) |
|
82 | 83 | members.each do |member| |
|
83 | 84 | MemberRole. |
|
84 |
in |
|
|
85 | joins(:member). | |
|
86 | references(:member). | |
|
85 | 87 | where("#{Member.table_name}.user_id = ? AND #{MemberRole.table_name}.inherited_from IN (?)", user.id, member.member_role_ids). |
|
86 | 88 | each(&:destroy) |
|
87 | 89 | end |
@@ -95,10 +97,6 class Group < Principal | |||
|
95 | 97 | super(attr_name, *args) |
|
96 | 98 | end |
|
97 | 99 | |
|
98 | def self.builtin_id(arg) | |
|
99 | (arg.anonymous? ? GroupAnonymous : GroupNonMember).instance_id | |
|
100 | end | |
|
101 | ||
|
102 | 100 | def self.anonymous |
|
103 | 101 | GroupAnonymous.load_instance |
|
104 | 102 | end |
@@ -23,8 +23,4 class GroupAnonymous < GroupBuiltin | |||
|
23 | 23 | def builtin_type |
|
24 | 24 | "anonymous" |
|
25 | 25 | end |
|
26 | ||
|
27 | def self.instance_id | |
|
28 | @@instance_id ||= load_instance.id | |
|
29 | end | |
|
30 | 26 | end |
@@ -37,7 +37,7 class GroupBuiltin < Group | |||
|
37 | 37 | class << self |
|
38 | 38 | def load_instance |
|
39 | 39 | return nil if self == GroupBuiltin |
|
40 |
instance = |
|
|
40 | instance = order('id').first || create_instance | |
|
41 | 41 | end |
|
42 | 42 | |
|
43 | 43 | def create_instance |
@@ -23,8 +23,4 class GroupNonMember < GroupBuiltin | |||
|
23 | 23 | def builtin_type |
|
24 | 24 | "non_member" |
|
25 | 25 | end |
|
26 | ||
|
27 | def self.instance_id | |
|
28 | @@instance_id ||= load_instance.id | |
|
29 | end | |
|
30 | 26 | end |
@@ -31,15 +31,12 class Issue < ActiveRecord::Base | |||
|
31 | 31 | |
|
32 | 32 | has_many :journals, :as => :journalized, :dependent => :destroy |
|
33 | 33 | has_many :visible_journals, |
|
34 | lambda {where(["(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))", false])}, | |
|
34 | 35 | :class_name => 'Journal', |
|
35 |
:as => :journalized |
|
|
36 | :conditions => Proc.new { | |
|
37 | ["(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))", false] | |
|
38 | }, | |
|
39 | :readonly => true | |
|
36 | :as => :journalized | |
|
40 | 37 | |
|
41 | 38 | has_many :time_entries, :dependent => :destroy |
|
42 |
has_and_belongs_to_many :changesets, |
|
|
39 | has_and_belongs_to_many :changesets, lambda {order("#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC")} | |
|
43 | 40 | |
|
44 | 41 | has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all |
|
45 | 42 | has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all |
@@ -49,14 +46,19 class Issue < ActiveRecord::Base | |||
|
49 | 46 | acts_as_customizable |
|
50 | 47 | acts_as_watchable |
|
51 | 48 | acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"], |
|
52 | :include => [:project, :visible_journals], | |
|
53 | 49 | # sort by id so that limited eager loading doesn't break with postgresql |
|
54 | :order_column => "#{table_name}.id" | |
|
50 | :order_column => "#{table_name}.id", | |
|
51 | :scope => lambda { joins(:project). | |
|
52 | joins("LEFT OUTER JOIN #{Journal.table_name} ON #{Journal.table_name}.journalized_type='Issue'" + | |
|
53 | " AND #{Journal.table_name}.journalized_id = #{Issue.table_name}.id" + | |
|
54 | " AND (#{Journal.table_name}.private_notes = #{connection.quoted_false}" + | |
|
55 | " OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))") } | |
|
56 | ||
|
55 | 57 | acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id} (#{o.status}): #{o.subject}"}, |
|
56 | 58 | :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}, |
|
57 | 59 | :type => Proc.new {|o| 'issue' + (o.closed? ? ' closed' : '') } |
|
58 | 60 | |
|
59 |
acts_as_activity_provider : |
|
|
61 | acts_as_activity_provider :scope => preload(:project, :author, :tracker), | |
|
60 | 62 | :author_key => :author_id |
|
61 | 63 | |
|
62 | 64 | DONE_RATIO_OPTIONS = %w(issue_field issue_status) |
@@ -72,19 +74,26 class Issue < ActiveRecord::Base | |||
|
72 | 74 | validates :start_date, :date => true |
|
73 | 75 | validates :due_date, :date => true |
|
74 | 76 | validate :validate_issue, :validate_required_fields |
|
77 | attr_protected :id | |
|
75 | 78 | |
|
76 | 79 | scope :visible, lambda {|*args| |
|
77 | includes(:project).where(Issue.visible_condition(args.shift || User.current, *args)) | |
|
80 | joins(:project). | |
|
81 | references(:project). | |
|
82 | where(Issue.visible_condition(args.shift || User.current, *args)) | |
|
78 | 83 | } |
|
79 | 84 | |
|
80 | 85 | scope :open, lambda {|*args| |
|
81 | 86 | is_closed = args.size > 0 ? !args.first : false |
|
82 | includes(:status).where("#{IssueStatus.table_name}.is_closed = ?", is_closed) | |
|
87 | joins(:status). | |
|
88 | references(:status). | |
|
89 | where("#{IssueStatus.table_name}.is_closed = ?", is_closed) | |
|
83 | 90 | } |
|
84 | 91 | |
|
85 | 92 | scope :recently_updated, lambda { order("#{Issue.table_name}.updated_on DESC") } |
|
86 | 93 | scope :on_active_project, lambda { |
|
87 | includes(:status, :project, :tracker).where("#{Project.table_name}.status = ?", Project::STATUS_ACTIVE) | |
|
94 | joins(:project). | |
|
95 | references(:project). | |
|
96 | where("#{Project.table_name}.status = ?", Project::STATUS_ACTIVE) | |
|
88 | 97 | } |
|
89 | 98 | scope :fixed_version, lambda {|versions| |
|
90 | 99 | ids = [versions].flatten.compact.map {|v| v.is_a?(Version) ? v.id : v} |
@@ -107,7 +116,7 class Issue < ActiveRecord::Base | |||
|
107 | 116 | # Returns a SQL conditions string used to find all issues visible by the specified user |
|
108 | 117 | def self.visible_condition(user, options={}) |
|
109 | 118 | Project.allowed_to_condition(user, :view_issues, options) do |role, user| |
|
110 | if user.logged? | |
|
119 | if user.id && user.logged? | |
|
111 | 120 | case role.issues_visibility |
|
112 | 121 | when 'all' |
|
113 | 122 | nil |
@@ -351,6 +360,10 class Issue < ActiveRecord::Base | |||
|
351 | 360 | # Do not redefine alias chain on reload (see #4838) |
|
352 | 361 | alias_method_chain(:assign_attributes, :project_and_tracker_first) unless method_defined?(:assign_attributes_without_project_and_tracker_first) |
|
353 | 362 | |
|
363 | def attributes=(new_attributes) | |
|
364 | assign_attributes new_attributes | |
|
365 | end | |
|
366 | ||
|
354 | 367 | def estimated_hours=(h) |
|
355 | 368 | write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h) |
|
356 | 369 | end |
@@ -423,7 +436,7 class Issue < ActiveRecord::Base | |||
|
423 | 436 | def safe_attributes=(attrs, user=User.current) |
|
424 | 437 | return unless attrs.is_a?(Hash) |
|
425 | 438 | |
|
426 | attrs = attrs.dup | |
|
439 | attrs = attrs.deep_dup | |
|
427 | 440 | |
|
428 | 441 | # Project and Tracker must be set before since new_statuses_allowed_to depends on it. |
|
429 | 442 | if (p = attrs.delete('project_id')) && safe_attribute?('project_id') |
@@ -458,14 +471,12 class Issue < ActiveRecord::Base | |||
|
458 | 471 | |
|
459 | 472 | if attrs['custom_field_values'].present? |
|
460 | 473 | editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s} |
|
461 | # TODO: use #select when ruby1.8 support is dropped | |
|
462 | attrs['custom_field_values'] = attrs['custom_field_values'].reject {|k, v| !editable_custom_field_ids.include?(k.to_s)} | |
|
474 | attrs['custom_field_values'].select! {|k, v| editable_custom_field_ids.include?(k.to_s)} | |
|
463 | 475 | end |
|
464 | 476 | |
|
465 | 477 | if attrs['custom_fields'].present? |
|
466 | 478 | editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s} |
|
467 | # TODO: use #select when ruby1.8 support is dropped | |
|
468 | attrs['custom_fields'] = attrs['custom_fields'].reject {|c| !editable_custom_field_ids.include?(c['id'].to_s)} | |
|
479 | attrs['custom_fields'].select! {|c| editable_custom_field_ids.include?(c['id'].to_s)} | |
|
469 | 480 | end |
|
470 | 481 | |
|
471 | 482 | # mass-assignment security bypass |
@@ -733,7 +744,7 class Issue < ActiveRecord::Base | |||
|
733 | 744 | def assignable_versions |
|
734 | 745 | return @assignable_versions if @assignable_versions |
|
735 | 746 | |
|
736 |
versions = project.shared_versions.open.a |
|
|
747 | versions = project.shared_versions.open.to_a | |
|
737 | 748 | if fixed_version |
|
738 | 749 | if fixed_version_id_changed? |
|
739 | 750 | # nothing to do |
@@ -879,10 +890,14 class Issue < ActiveRecord::Base | |||
|
879 | 890 | if issues.any? |
|
880 | 891 | issue_ids = issues.map(&:id) |
|
881 | 892 | # Relations with issue_from in given issues and visible issue_to |
|
882 | relations_from = IssueRelation.includes(:issue_to => [:status, :project]).where(visible_condition(user)).where(:issue_from_id => issue_ids).all | |
|
893 | relations_from = IssueRelation.joins(:issue_to => :project). | |
|
894 | references(:issue_to => :project). | |
|
895 | where(visible_condition(user)).where(:issue_from_id => issue_ids).to_a | |
|
883 | 896 | # Relations with issue_to in given issues and visible issue_from |
|
884 |
relations_to = IssueRelation.in |
|
|
885 | ||
|
897 | relations_to = IssueRelation.joins(:issue_from => :project). | |
|
898 | references(:issue_from => :project). | |
|
899 | where(visible_condition(user)). | |
|
900 | where(:issue_to_id => issue_ids).to_a | |
|
886 | 901 | issues.each do |issue| |
|
887 | 902 | relations = |
|
888 | 903 | relations_from.select {|relation| relation.issue_from_id == issue.id} + |
@@ -1121,6 +1136,7 class Issue < ActiveRecord::Base | |||
|
1121 | 1136 | def parent_issue_id=(arg) |
|
1122 | 1137 | s = arg.to_s.strip.presence |
|
1123 | 1138 | if s && (m = s.match(%r{\A#?(\d+)\z})) && (@parent_issue = Issue.find_by_id(m[1])) |
|
1139 | @parent_issue.id | |
|
1124 | 1140 | @invalid_parent_issue_id = nil |
|
1125 | 1141 | elsif s.blank? |
|
1126 | 1142 | @parent_issue = nil |
@@ -1349,7 +1365,7 class Issue < ActiveRecord::Base | |||
|
1349 | 1365 | self.root_id = (@parent_issue.nil? ? id : @parent_issue.root_id) |
|
1350 | 1366 | cond = ["root_id = ? AND lft >= ? AND rgt <= ? ", old_root_id, lft, rgt] |
|
1351 | 1367 | self.class.base_class.select('id').lock(true).where(cond) |
|
1352 | offset = right_most_bound + 1 - lft | |
|
1368 | offset = rdm_right_most_bound + 1 - lft | |
|
1353 | 1369 | Issue.where(cond). |
|
1354 | 1370 | update_all(["root_id = ?, lft = lft + ?, rgt = rgt + ?", root_id, offset, offset]) |
|
1355 | 1371 | end |
@@ -1367,6 +1383,14 class Issue < ActiveRecord::Base | |||
|
1367 | 1383 | recalculate_attributes_for(former_parent_id) if former_parent_id |
|
1368 | 1384 | end |
|
1369 | 1385 | |
|
1386 | def rdm_right_most_bound | |
|
1387 | right_most_node = | |
|
1388 | self.class.base_class.unscoped. | |
|
1389 | order("#{quoted_right_column_full_name} desc").limit(1).lock(true).first | |
|
1390 | right_most_node ? (right_most_node[right_column_name] || 0 ) : 0 | |
|
1391 | end | |
|
1392 | private :rdm_right_most_bound | |
|
1393 | ||
|
1370 | 1394 | def update_parent_attributes |
|
1371 | 1395 | recalculate_attributes_for(parent_id) if parent_id |
|
1372 | 1396 | end |
@@ -1395,7 +1419,7 class Issue < ActiveRecord::Base | |||
|
1395 | 1419 | end |
|
1396 | 1420 | done = p.leaves.joins(:status). |
|
1397 | 1421 | sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " + |
|
1398 | "* (CASE WHEN is_closed = #{connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f | |
|
1422 | "* (CASE WHEN is_closed = #{self.class.connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f | |
|
1399 | 1423 | progress = done / (average * leaves_count) |
|
1400 | 1424 | p.done_ratio = progress.round |
|
1401 | 1425 | end |
@@ -1415,7 +1439,8 class Issue < ActiveRecord::Base | |||
|
1415 | 1439 | def self.update_versions(conditions=nil) |
|
1416 | 1440 | # Only need to update issues with a fixed_version from |
|
1417 | 1441 | # a different project and that is not systemwide shared |
|
1418 |
Issue.in |
|
|
1442 | Issue.joins(:project, :fixed_version). | |
|
1443 | references(:version, :fixed_version). | |
|
1419 | 1444 | where("#{Issue.table_name}.fixed_version_id IS NOT NULL" + |
|
1420 | 1445 | " AND #{Issue.table_name}.project_id <> #{Version.table_name}.project_id" + |
|
1421 | 1446 | " AND #{Version.table_name}.sharing <> 'system'"). |
@@ -24,6 +24,7 class IssueCategory < ActiveRecord::Base | |||
|
24 | 24 | validates_presence_of :name |
|
25 | 25 | validates_uniqueness_of :name, :scope => [:project_id] |
|
26 | 26 | validates_length_of :name, :maximum => 30 |
|
27 | attr_protected :id | |
|
27 | 28 | |
|
28 | 29 | safe_attributes 'name', 'assigned_to_id' |
|
29 | 30 |
@@ -32,7 +32,7 class IssueCustomField < CustomField | |||
|
32 | 32 | sql = super |
|
33 | 33 | id_column ||= id |
|
34 | 34 | tracker_condition = "#{Issue.table_name}.tracker_id IN (SELECT tracker_id FROM #{table_name_prefix}custom_fields_trackers#{table_name_suffix} WHERE custom_field_id = #{id_column})" |
|
35 | project_condition = "EXISTS (SELECT 1 FROM #{CustomField.table_name} ifa WHERE ifa.is_for_all = #{connection.quoted_true} AND ifa.id = #{id_column})" + | |
|
35 | project_condition = "EXISTS (SELECT 1 FROM #{CustomField.table_name} ifa WHERE ifa.is_for_all = #{self.class.connection.quoted_true} AND ifa.id = #{id_column})" + | |
|
36 | 36 | " OR #{Issue.table_name}.project_id IN (SELECT project_id FROM #{table_name_prefix}custom_fields_projects#{table_name_suffix} WHERE custom_field_id = #{id_column})" |
|
37 | 37 | |
|
38 | 38 | "((#{sql}) AND (#{tracker_condition}) AND (#{project_condition}))" |
@@ -45,7 +45,9 class IssueQuery < Query | |||
|
45 | 45 | scope :visible, lambda {|*args| |
|
46 | 46 | user = args.shift || User.current |
|
47 | 47 | base = Project.allowed_to_condition(user, :view_issues, *args) |
|
48 | scope = includes(:project).where("#{table_name}.project_id IS NULL OR (#{base})") | |
|
48 | scope = joins("LEFT OUTER JOIN #{Project.table_name} ON #{table_name}.project_id = #{Project.table_name}.id"). | |
|
49 | references(:project). | |
|
50 | where("#{table_name}.project_id IS NULL OR (#{base})") | |
|
49 | 51 | |
|
50 | 52 | if user.admin? |
|
51 | 53 | scope.where("#{table_name}.visibility <> ? OR #{table_name}.user_id = ?", VISIBILITY_PRIVATE, user.id) |
@@ -132,17 +134,17 class IssueQuery < Query | |||
|
132 | 134 | if project |
|
133 | 135 | principals += project.principals.sort |
|
134 | 136 | unless project.leaf? |
|
135 |
subprojects = project.descendants.visible.a |
|
|
137 | subprojects = project.descendants.visible.to_a | |
|
136 | 138 | principals += Principal.member_of(subprojects) |
|
137 | 139 | end |
|
138 |
versions = project.shared_versions.a |
|
|
139 |
categories = project.issue_categories.a |
|
|
140 | versions = project.shared_versions.to_a | |
|
141 | categories = project.issue_categories.to_a | |
|
140 | 142 | issue_custom_fields = project.all_issue_custom_fields |
|
141 | 143 | else |
|
142 | 144 | if all_projects.any? |
|
143 | 145 | principals += Principal.member_of(all_projects) |
|
144 | 146 | end |
|
145 |
versions = Version.visible.where(:sharing => 'system').a |
|
|
147 | versions = Version.visible.where(:sharing => 'system').to_a | |
|
146 | 148 | issue_custom_fields = IssueCustomField.where(:is_for_all => true) |
|
147 | 149 | end |
|
148 | 150 | principals.uniq! |
@@ -339,7 +341,7 class IssueQuery < Query | |||
|
339 | 341 | scope = scope.preload(:author) |
|
340 | 342 | end |
|
341 | 343 | |
|
342 |
issues = scope.a |
|
|
344 | issues = scope.to_a | |
|
343 | 345 | |
|
344 | 346 | if has_column?(:spent_hours) |
|
345 | 347 | Issue.load_visible_spent_hours(issues) |
@@ -360,12 +362,13 class IssueQuery < Query | |||
|
360 | 362 | joins(:status, :project). |
|
361 | 363 | where(statement). |
|
362 | 364 | includes(([:status, :project] + (options[:include] || [])).uniq). |
|
365 | references(([:status, :project] + (options[:include] || [])).uniq). | |
|
363 | 366 | where(options[:conditions]). |
|
364 | 367 | order(order_option). |
|
365 | 368 | joins(joins_for_order_statement(order_option.join(','))). |
|
366 | 369 | limit(options[:limit]). |
|
367 | 370 | offset(options[:offset]). |
|
368 | find_ids | |
|
371 | pluck(:id) | |
|
369 | 372 | rescue ::ActiveRecord::StatementInvalid => e |
|
370 | 373 | raise StatementInvalid.new(e.message) |
|
371 | 374 | end |
@@ -380,7 +383,7 class IssueQuery < Query | |||
|
380 | 383 | limit(options[:limit]). |
|
381 | 384 | offset(options[:offset]). |
|
382 | 385 | preload(:details, :user, {:issue => [:project, :author, :tracker, :status]}). |
|
383 |
a |
|
|
386 | to_a | |
|
384 | 387 | rescue ::ActiveRecord::StatementInvalid => e |
|
385 | 388 | raise StatementInvalid.new(e.message) |
|
386 | 389 | end |
@@ -392,7 +395,8 class IssueQuery < Query | |||
|
392 | 395 | where(project_statement). |
|
393 | 396 | where(options[:conditions]). |
|
394 | 397 | includes(:project). |
|
395 | all | |
|
398 | references(:project). | |
|
399 | to_a | |
|
396 | 400 | rescue ::ActiveRecord::StatementInvalid => e |
|
397 | 401 | raise StatementInvalid.new(e.message) |
|
398 | 402 | end |
@@ -411,7 +415,7 class IssueQuery < Query | |||
|
411 | 415 | groups = Group.givable |
|
412 | 416 | operator = '!' # Override the operator since we want to find by assigned_to |
|
413 | 417 | else |
|
414 |
groups = Group.where(:id => value).a |
|
|
418 | groups = Group.where(:id => value).to_a | |
|
415 | 419 | end |
|
416 | 420 | groups ||= [] |
|
417 | 421 | |
@@ -431,7 +435,7 class IssueQuery < Query | |||
|
431 | 435 | " WHERE #{Member.table_name}.project_id = #{Issue.table_name}.project_id))" |
|
432 | 436 | when "=", "!" |
|
433 | 437 | role_cond = value.any? ? |
|
434 | "#{MemberRole.table_name}.role_id IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")" : | |
|
438 | "#{MemberRole.table_name}.role_id IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + ")" : | |
|
435 | 439 | "1=0" |
|
436 | 440 | |
|
437 | 441 | sw = operator == "!" ? 'NOT' : '' |
@@ -443,7 +447,7 class IssueQuery < Query | |||
|
443 | 447 | |
|
444 | 448 | def sql_for_is_private_field(field, operator, value) |
|
445 | 449 | op = (operator == "=" ? 'IN' : 'NOT IN') |
|
446 | va = value.map {|v| v == '0' ? connection.quoted_false : connection.quoted_true}.uniq.join(',') | |
|
450 | va = value.map {|v| v == '0' ? self.class.connection.quoted_false : self.class.connection.quoted_true}.uniq.join(',') | |
|
447 | 451 | |
|
448 | 452 | "#{Issue.table_name}.is_private #{op} (#{va})" |
|
449 | 453 | end |
@@ -462,14 +466,14 class IssueQuery < Query | |||
|
462 | 466 | sql = case operator |
|
463 | 467 | when "*", "!*" |
|
464 | 468 | op = (operator == "*" ? 'IN' : 'NOT IN') |
|
465 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}')" | |
|
469 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}')" | |
|
466 | 470 | when "=", "!" |
|
467 | 471 | op = (operator == "=" ? 'IN' : 'NOT IN') |
|
468 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})" | |
|
472 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})" | |
|
469 | 473 | when "=p", "=!p", "!p" |
|
470 | 474 | op = (operator == "!p" ? 'NOT IN' : 'IN') |
|
471 | 475 | comp = (operator == "=!p" ? '<>' : '=') |
|
472 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})" | |
|
476 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})" | |
|
473 | 477 | end |
|
474 | 478 | |
|
475 | 479 | if relation_options[:sym] == field && !options[:reverse] |
@@ -27,6 +27,7 class IssueStatus < ActiveRecord::Base | |||
|
27 | 27 | validates_uniqueness_of :name |
|
28 | 28 | validates_length_of :name, :maximum => 30 |
|
29 | 29 | validates_inclusion_of :default_done_ratio, :in => 0..100, :allow_nil => true |
|
30 | attr_protected :id | |
|
30 | 31 | |
|
31 | 32 | scope :sorted, lambda { order("#{table_name}.position ASC") } |
|
32 | 33 | scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)} |
@@ -79,7 +80,7 class IssueStatus < ActiveRecord::Base | |||
|
79 | 80 | includes(:new_status). |
|
80 | 81 | where(["role_id IN (:role_ids) AND tracker_id = :tracker_id AND (#{conditions})", |
|
81 | 82 | {:role_ids => roles.collect(&:id), :tracker_id => tracker.id, :true => true, :false => false} |
|
82 |
]).a |
|
|
83 | ]).to_a. | |
|
83 | 84 | map(&:new_status).compact.sort |
|
84 | 85 | else |
|
85 | 86 | [] |
@@ -24,6 +24,7 class Journal < ActiveRecord::Base | |||
|
24 | 24 | belongs_to :user |
|
25 | 25 | has_many :details, :class_name => "JournalDetail", :dependent => :delete_all |
|
26 | 26 | attr_accessor :indice |
|
27 | attr_protected :id | |
|
27 | 28 | |
|
28 | 29 | acts_as_event :title => Proc.new {|o| status = ((s = o.new_status) ? " (#{s})" : nil); "#{o.issue.tracker} ##{o.issue.id}#{status}: #{o.issue.subject}" }, |
|
29 | 30 | :description => :notes, |
@@ -34,17 +35,18 class Journal < ActiveRecord::Base | |||
|
34 | 35 | |
|
35 | 36 | acts_as_activity_provider :type => 'issues', |
|
36 | 37 | :author_key => :user_id, |
|
37 |
: |
|
|
38 | :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" + | |
|
39 | " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"} | |
|
38 | :scope => preload({:issue => :project}, :user). | |
|
39 | joins("LEFT OUTER JOIN #{JournalDetail.table_name} ON #{JournalDetail.table_name}.journal_id = #{Journal.table_name}.id"). | |
|
40 | where("#{Journal.table_name}.journalized_type = 'Issue' AND" + | |
|
41 | " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')") | |
|
40 | 42 | |
|
41 | 43 | before_create :split_private_notes |
|
42 | 44 | after_create :send_notification |
|
43 | 45 | |
|
44 | 46 | scope :visible, lambda {|*args| |
|
45 | 47 | user = args.shift || User.current |
|
46 | ||
|
47 |
|
|
|
48 | joins(:issue => :project). | |
|
49 | references(:project). | |
|
48 | 50 | where(Issue.visible_condition(user, *args)). |
|
49 | 51 | where("(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes, *args)}))", false) |
|
50 | 52 | } |
@@ -18,6 +18,7 | |||
|
18 | 18 | class JournalDetail < ActiveRecord::Base |
|
19 | 19 | belongs_to :journal |
|
20 | 20 | before_save :normalize_values |
|
21 | attr_protected :id | |
|
21 | 22 | |
|
22 | 23 | def custom_field |
|
23 | 24 | if property == 'cf' |
@@ -42,7 +42,7 class MailHandler < ActionMailer::Base | |||
|
42 | 42 | @@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1') |
|
43 | 43 | @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1') |
|
44 | 44 | |
|
45 |
email.force_encoding('ASCII-8BIT') |
|
|
45 | email.force_encoding('ASCII-8BIT') | |
|
46 | 46 | super(email) |
|
47 | 47 | end |
|
48 | 48 | |
@@ -417,7 +417,7 class MailHandler < ActionMailer::Base | |||
|
417 | 417 | end |
|
418 | 418 | |
|
419 | 419 | parts.reject! do |part| |
|
420 | part.header[:content_disposition].try(:disposition_type) == 'attachment' | |
|
420 | part.attachment? | |
|
421 | 421 | end |
|
422 | 422 | |
|
423 | 423 | @plain_text_body = parts.map do |p| |
@@ -25,6 +25,7 class Member < ActiveRecord::Base | |||
|
25 | 25 | validates_presence_of :principal, :project |
|
26 | 26 | validates_uniqueness_of :user_id, :scope => :project_id |
|
27 | 27 | validate :validate_role |
|
28 | attr_protected :id | |
|
28 | 29 | |
|
29 | 30 | before_destroy :set_issue_category_nil |
|
30 | 31 |
@@ -26,6 +26,7 class MemberRole < ActiveRecord::Base | |||
|
26 | 26 | |
|
27 | 27 | validates_presence_of :role |
|
28 | 28 | validate :validate_role_member |
|
29 | attr_protected :id | |
|
29 | 30 | |
|
30 | 31 | def validate_role_member |
|
31 | 32 | errors.add :role_id, :invalid if role && !role.member? |
@@ -22,9 +22,10 class Message < ActiveRecord::Base | |||
|
22 | 22 | acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC" |
|
23 | 23 | acts_as_attachable |
|
24 | 24 | belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id' |
|
25 | attr_protected :id | |
|
25 | 26 | |
|
26 | 27 | acts_as_searchable :columns => ['subject', 'content'], |
|
27 |
: |
|
|
28 | :scope => preload(:board => :project), | |
|
28 | 29 | :project_key => "#{Board.table_name}.project_id", |
|
29 | 30 | :date_column => "#{table_name}.created_on" |
|
30 | 31 | acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"}, |
@@ -34,7 +35,7 class Message < ActiveRecord::Base | |||
|
34 | 35 | :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} : |
|
35 | 36 | {:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})} |
|
36 | 37 | |
|
37 |
acts_as_activity_provider : |
|
|
38 | acts_as_activity_provider :scope => preload({:board => :project}, :author), | |
|
38 | 39 | :author_key => :author_id |
|
39 | 40 | acts_as_watchable |
|
40 | 41 | |
@@ -48,7 +49,9 class Message < ActiveRecord::Base | |||
|
48 | 49 | after_create :send_notification |
|
49 | 50 | |
|
50 | 51 | scope :visible, lambda {|*args| |
|
51 | includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args)) | |
|
52 | joins(:board => :project). | |
|
53 | references(:board => :project). | |
|
54 | where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args)) | |
|
52 | 55 | } |
|
53 | 56 | |
|
54 | 57 | safe_attributes 'subject', 'content' |
@@ -19,16 +19,18 class News < ActiveRecord::Base | |||
|
19 | 19 | include Redmine::SafeAttributes |
|
20 | 20 | belongs_to :project |
|
21 | 21 | belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' |
|
22 |
has_many :comments, :as => :commented, :dependent => :delete_all |
|
|
22 | has_many :comments, lambda {order("created_on")}, :as => :commented, :dependent => :delete_all | |
|
23 | 23 | |
|
24 | 24 | validates_presence_of :title, :description |
|
25 | 25 | validates_length_of :title, :maximum => 60 |
|
26 | 26 | validates_length_of :summary, :maximum => 255 |
|
27 | attr_protected :id | |
|
27 | 28 | |
|
28 | 29 | acts_as_attachable :delete_permission => :manage_news |
|
29 |
acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], |
|
|
30 | acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], | |
|
31 | :scope => preload(:project) | |
|
30 | 32 | acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} |
|
31 |
acts_as_activity_provider : |
|
|
33 | acts_as_activity_provider :scope => preload(:project, :author), | |
|
32 | 34 | :author_key => :author_id |
|
33 | 35 | acts_as_watchable |
|
34 | 36 | |
@@ -36,7 +38,9 class News < ActiveRecord::Base | |||
|
36 | 38 | after_create :send_notification |
|
37 | 39 | |
|
38 | 40 | scope :visible, lambda {|*args| |
|
39 | includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args)) | |
|
41 | joins(:project). | |
|
42 | references([:author, :project]). | |
|
43 | where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args)) | |
|
40 | 44 | } |
|
41 | 45 | |
|
42 | 46 | safe_attributes 'title', 'summary', 'description' |
@@ -68,7 +72,7 class News < ActiveRecord::Base | |||
|
68 | 72 | |
|
69 | 73 | # returns latest news for projects visible by user |
|
70 | 74 | def self.latest(user = User.current, count = 5) |
|
71 |
visible(user).in |
|
|
75 | visible(user).joins([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).to_a | |
|
72 | 76 | end |
|
73 | 77 | |
|
74 | 78 | private |
@@ -25,11 +25,13 class Principal < ActiveRecord::Base | |||
|
25 | 25 | STATUS_LOCKED = 3 |
|
26 | 26 | |
|
27 | 27 | has_many :members, :foreign_key => 'user_id', :dependent => :destroy |
|
28 |
has_many :memberships, |
|
|
29 | :foreign_key => 'user_id', | |
|
30 | :include => [:project, :roles], | |
|
31 |
|
|
|
32 |
|
|
|
28 | has_many :memberships, | |
|
29 | lambda {preload(:project, :roles). | |
|
30 | joins(:project). | |
|
31 | where("#{Project.table_name}.status<>#{Project::STATUS_ARCHIVED}"). | |
|
32 | order("#{Project.table_name}.name")}, | |
|
33 | :class_name => 'Member', | |
|
34 | :foreign_key => 'user_id' | |
|
33 | 35 | has_many :projects, :through => :memberships |
|
34 | 36 | has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify |
|
35 | 37 | |
@@ -56,8 +58,8 class Principal < ActiveRecord::Base | |||
|
56 | 58 | |
|
57 | 59 | # Principals that are members of a collection of projects |
|
58 | 60 | scope :member_of, lambda {|projects| |
|
59 |
projects = [projects] |
|
|
60 |
if projects. |
|
|
61 | projects = [projects] if projects.is_a?(Project) | |
|
62 | if projects.blank? | |
|
61 | 63 | where("1=0") |
|
62 | 64 | else |
|
63 | 65 | ids = projects.map(&:id) |
@@ -28,31 +28,35 class Project < ActiveRecord::Base | |||
|
28 | 28 | |
|
29 | 29 | # Specific overridden Activities |
|
30 | 30 | has_many :time_entry_activities |
|
31 | has_many :members, :include => [:principal, :roles], :conditions => "#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}" | |
|
31 | has_many :members, | |
|
32 | lambda { joins(:principal, :roles). | |
|
33 | references(:principal, :roles). | |
|
34 | where("#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}") } | |
|
32 | 35 | has_many :memberships, :class_name => 'Member' |
|
33 |
has_many :member_principals, |
|
|
34 | :include => :principal, | |
|
35 | :conditions => "#{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}" | |
|
36 | ||
|
36 | has_many :member_principals, | |
|
37 | lambda { joins(:principal). | |
|
38 | references(:principal). | |
|
39 | where("#{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}")}, | |
|
40 | :class_name => 'Member' | |
|
37 | 41 | has_many :enabled_modules, :dependent => :delete_all |
|
38 |
has_and_belongs_to_many :trackers, |
|
|
39 |
has_many :issues, :dependent => :destroy |
|
|
42 | has_and_belongs_to_many :trackers, lambda {order("#{Tracker.table_name}.position")} | |
|
43 | has_many :issues, :dependent => :destroy | |
|
40 | 44 | has_many :issue_changes, :through => :issues, :source => :journals |
|
41 |
has_many :versions, |
|
|
45 | has_many :versions, lambda {order("#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC")}, :dependent => :destroy | |
|
42 | 46 | has_many :time_entries, :dependent => :destroy |
|
43 | 47 | has_many :queries, :class_name => 'IssueQuery', :dependent => :delete_all |
|
44 | 48 | has_many :documents, :dependent => :destroy |
|
45 |
has_many :news, :dependent => :destroy |
|
|
46 |
has_many :issue_categories, :dependent => :delete_all |
|
|
47 | has_many :boards, :dependent => :destroy, :order => "position ASC" | |
|
48 |
has_one :repository, |
|
|
49 | has_many :news, lambda {includes(:author)}, :dependent => :destroy | |
|
50 | has_many :issue_categories, lambda {order("#{IssueCategory.table_name}.name")}, :dependent => :delete_all | |
|
51 | has_many :boards, lambda {order("position ASC")}, :dependent => :destroy | |
|
52 | has_one :repository, lambda {where(["is_default = ?", true])} | |
|
49 | 53 | has_many :repositories, :dependent => :destroy |
|
50 | 54 | has_many :changesets, :through => :repository |
|
51 | 55 | has_one :wiki, :dependent => :destroy |
|
52 | 56 | # Custom field for the project issues |
|
53 | 57 | has_and_belongs_to_many :issue_custom_fields, |
|
58 | lambda {order("#{CustomField.table_name}.position")}, | |
|
54 | 59 | :class_name => 'IssueCustomField', |
|
55 | :order => "#{CustomField.table_name}.position", | |
|
56 | 60 | :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", |
|
57 | 61 | :association_foreign_key => 'custom_field_id' |
|
58 | 62 | |
@@ -126,9 +130,9 class Project < ActiveRecord::Base | |||
|
126 | 130 | if !initialized.key?('trackers') && !initialized.key?('tracker_ids') |
|
127 | 131 | default = Setting.default_projects_tracker_ids |
|
128 | 132 | if default.is_a?(Array) |
|
129 |
self.trackers = Tracker.where(:id => default.map(&:to_i)).sorted.a |
|
|
133 | self.trackers = Tracker.where(:id => default.map(&:to_i)).sorted.to_a | |
|
130 | 134 | else |
|
131 |
self.trackers = Tracker.sorted.a |
|
|
135 | self.trackers = Tracker.sorted.to_a | |
|
132 | 136 | end |
|
133 | 137 | end |
|
134 | 138 | end |
@@ -144,7 +148,7 class Project < ActiveRecord::Base | |||
|
144 | 148 | # returns latest created projects |
|
145 | 149 | # non public projects will be returned only if user is a member of those |
|
146 | 150 | def self.latest(user=nil, count=5) |
|
147 |
visible(user).limit(count).order("created_on DESC").a |
|
|
151 | visible(user).limit(count).order("created_on DESC").to_a | |
|
148 | 152 | end |
|
149 | 153 | |
|
150 | 154 | # Returns true if the project is visible to +user+ or to the current user. |
@@ -212,9 +216,9 class Project < ActiveRecord::Base | |||
|
212 | 216 | end |
|
213 | 217 | |
|
214 | 218 | def override_roles(role) |
|
215 | @override_members ||= memberships.where(:user_id => [GroupAnonymous.instance_id, GroupNonMember.instance_id]).all | |
|
216 | member = @override_members.detect {|m| role.anonymous? ^ (m.user_id == GroupNonMember.instance_id)} | |
|
217 | member ? member.roles : [role] | |
|
219 | group_class = role.anonymous? ? GroupAnonymous : GroupNonMember | |
|
220 | member = member_principals.where("#{Principal.table_name}.type = ?", group_class.name).first | |
|
221 | member ? member.roles.to_a : [role] | |
|
218 | 222 | end |
|
219 | 223 | |
|
220 | 224 | def principals |
@@ -364,7 +368,7 class Project < ActiveRecord::Base | |||
|
364 | 368 | # by the current user |
|
365 | 369 | def allowed_parents |
|
366 | 370 | return @allowed_parents if @allowed_parents |
|
367 |
@allowed_parents = Project.where(Project.allowed_to_condition(User.current, :add_subprojects)).a |
|
|
371 | @allowed_parents = Project.where(Project.allowed_to_condition(User.current, :add_subprojects)).to_a | |
|
368 | 372 | @allowed_parents = @allowed_parents - self_and_descendants |
|
369 | 373 | if User.current.allowed_to?(:add_project, nil, :global => true) || (!new_record? && parent.nil?) |
|
370 | 374 | @allowed_parents << nil |
@@ -435,11 +439,12 class Project < ActiveRecord::Base | |||
|
435 | 439 | @rolled_up_trackers ||= |
|
436 | 440 | Tracker. |
|
437 | 441 | joins(:projects). |
|
442 | references(:project). | |
|
438 | 443 | joins("JOIN #{EnabledModule.table_name} ON #{EnabledModule.table_name}.project_id = #{Project.table_name}.id AND #{EnabledModule.table_name}.name = 'issue_tracking'"). |
|
439 | 444 | select("DISTINCT #{Tracker.table_name}.*"). |
|
440 | 445 | where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> #{STATUS_ARCHIVED}", lft, rgt). |
|
441 | 446 | sorted. |
|
442 |
a |
|
|
447 | to_a | |
|
443 | 448 | end |
|
444 | 449 | |
|
445 | 450 | # Closes open and locked project versions that are completed |
@@ -457,7 +462,8 class Project < ActiveRecord::Base | |||
|
457 | 462 | def rolled_up_versions |
|
458 | 463 | @rolled_up_versions ||= |
|
459 | 464 | Version. |
|
460 |
in |
|
|
465 | joins(:project). | |
|
466 | references(:project). | |
|
461 | 467 | where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> ?", lft, rgt, STATUS_ARCHIVED) |
|
462 | 468 | end |
|
463 | 469 | |
@@ -465,13 +471,17 class Project < ActiveRecord::Base | |||
|
465 | 471 | def shared_versions |
|
466 | 472 | if new_record? |
|
467 | 473 | Version. |
|
468 |
in |
|
|
474 | joins(:project). | |
|
475 | references(:project). | |
|
476 | preload(:project). | |
|
469 | 477 | where("#{Project.table_name}.status <> ? AND #{Version.table_name}.sharing = 'system'", STATUS_ARCHIVED) |
|
470 | 478 | else |
|
471 | 479 | @shared_versions ||= begin |
|
472 | 480 | r = root? ? self : root |
|
473 | 481 | Version. |
|
474 |
in |
|
|
482 | joins(:project). | |
|
483 | references(:project). | |
|
484 | preload(:project). | |
|
475 | 485 | where("#{Project.table_name}.id = #{id}" + |
|
476 | 486 | " OR (#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED} AND (" + |
|
477 | 487 | " #{Version.table_name}.sharing = 'system'" + |
@@ -497,7 +507,7 class Project < ActiveRecord::Base | |||
|
497 | 507 | # Deletes all project's members |
|
498 | 508 | def delete_all_members |
|
499 | 509 | me, mr = Member.table_name, MemberRole.table_name |
|
500 | connection.delete("DELETE FROM #{mr} WHERE #{mr}.member_id IN (SELECT #{me}.id FROM #{me} WHERE #{me}.project_id = #{id})") | |
|
510 | self.class.connection.delete("DELETE FROM #{mr} WHERE #{mr}.member_id IN (SELECT #{me}.id FROM #{me} WHERE #{me}.project_id = #{id})") | |
|
501 | 511 | Member.delete_all(['project_id = ?', id]) |
|
502 | 512 | end |
|
503 | 513 | |
@@ -728,7 +738,7 class Project < ActiveRecord::Base | |||
|
728 | 738 | project = project.is_a?(Project) ? project : Project.find(project) |
|
729 | 739 | |
|
730 | 740 | to_be_copied = %w(wiki versions issue_categories issues members queries boards) |
|
731 |
to_be_copied = to_be_copied & options[:only] |
|
|
741 | to_be_copied = to_be_copied & Array.wrap(options[:only]) unless options[:only].nil? | |
|
732 | 742 | |
|
733 | 743 | Project.transaction do |
|
734 | 744 | if save |
@@ -740,6 +750,7 class Project < ActiveRecord::Base | |||
|
740 | 750 | save |
|
741 | 751 | end |
|
742 | 752 | end |
|
753 | true | |
|
743 | 754 | end |
|
744 | 755 | |
|
745 | 756 | # Returns a new unsaved Project instance with attributes copied from +project+ |
@@ -958,11 +969,10 class Project < ActiveRecord::Base | |||
|
958 | 969 | def copy_queries(project) |
|
959 | 970 | project.queries.each do |query| |
|
960 | 971 | new_query = IssueQuery.new |
|
961 |
new_query.attributes = query.attributes.dup.except("id", "project_id", "sort_criteria" |
|
|
972 | new_query.attributes = query.attributes.dup.except("id", "project_id", "sort_criteria") | |
|
962 | 973 | new_query.sort_criteria = query.sort_criteria if query.sort_criteria |
|
963 | 974 | new_query.project = self |
|
964 | 975 | new_query.user_id = query.user_id |
|
965 | new_query.role_ids = query.role_ids if query.visibility == IssueQuery::VISIBILITY_ROLES | |
|
966 | 976 | self.queries << new_query |
|
967 | 977 | end |
|
968 | 978 | end |
@@ -288,7 +288,7 class Query < ActiveRecord::Base | |||
|
288 | 288 | end |
|
289 | 289 | |
|
290 | 290 | def trackers |
|
291 |
@trackers ||= project.nil? ? Tracker.sorted.a |
|
|
291 | @trackers ||= project.nil? ? Tracker.sorted.to_a : project.rolled_up_trackers | |
|
292 | 292 | end |
|
293 | 293 | |
|
294 | 294 | # Returns a hash of localized labels for all filter operators |
@@ -306,7 +306,7 class Query < ActiveRecord::Base | |||
|
306 | 306 | end |
|
307 | 307 | |
|
308 | 308 | def all_projects |
|
309 |
@all_projects ||= Project.visible.a |
|
|
309 | @all_projects ||= Project.visible.to_a | |
|
310 | 310 | end |
|
311 | 311 | |
|
312 | 312 | def all_projects_values |
@@ -655,7 +655,7 class Query < ActiveRecord::Base | |||
|
655 | 655 | sql = "#{db_table}.#{db_field} BETWEEN #{value.first.to_f - 1e-5} AND #{value.first.to_f + 1e-5}" |
|
656 | 656 | end |
|
657 | 657 | else |
|
658 | sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")" | |
|
658 | sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + ")" | |
|
659 | 659 | end |
|
660 | 660 | else |
|
661 | 661 | # IN an empty set |
@@ -663,7 +663,7 class Query < ActiveRecord::Base | |||
|
663 | 663 | end |
|
664 | 664 | when "!" |
|
665 | 665 | if value.any? |
|
666 | sql = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" | |
|
666 | sql = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + "))" | |
|
667 | 667 | else |
|
668 | 668 | # NOT IN an empty set |
|
669 | 669 | sql = "1=1" |
@@ -705,9 +705,9 class Query < ActiveRecord::Base | |||
|
705 | 705 | end |
|
706 | 706 | end |
|
707 | 707 | when "o" |
|
708 | sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{connection.quoted_false})" if field == "status_id" | |
|
708 | sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_false})" if field == "status_id" | |
|
709 | 709 | when "c" |
|
710 | sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{connection.quoted_true})" if field == "status_id" | |
|
710 | sql = "#{queried_table_name}.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_true})" if field == "status_id" | |
|
711 | 711 | when "><t-" |
|
712 | 712 | # between today - n days and today |
|
713 | 713 | sql = relative_date_clause(db_table, db_field, - value.first.to_i, 0) |
@@ -769,9 +769,9 class Query < ActiveRecord::Base | |||
|
769 | 769 | date = Date.today |
|
770 | 770 | sql = date_clause(db_table, db_field, date.beginning_of_year, date.end_of_year) |
|
771 | 771 | when "~" |
|
772 | sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'" | |
|
772 | sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{self.class.connection.quote_string(value.first.to_s.downcase)}%'" | |
|
773 | 773 | when "!~" |
|
774 | sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'" | |
|
774 | sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{self.class.connection.quote_string(value.first.to_s.downcase)}%'" | |
|
775 | 775 | else |
|
776 | 776 | raise "Unknown query operator #{operator}" |
|
777 | 777 | end |
@@ -834,7 +834,7 class Query < ActiveRecord::Base | |||
|
834 | 834 | if self.class.default_timezone == :utc |
|
835 | 835 | from = from.utc |
|
836 | 836 | end |
|
837 | s << ("#{table}.#{field} > '%s'" % [connection.quoted_date(from)]) | |
|
837 | s << ("#{table}.#{field} > '%s'" % [self.class.connection.quoted_date(from)]) | |
|
838 | 838 | end |
|
839 | 839 | if to |
|
840 | 840 | if to.is_a?(Date) |
@@ -843,7 +843,7 class Query < ActiveRecord::Base | |||
|
843 | 843 | if self.class.default_timezone == :utc |
|
844 | 844 | to = to.utc |
|
845 | 845 | end |
|
846 | s << ("#{table}.#{field} <= '%s'" % [connection.quoted_date(to)]) | |
|
846 | s << ("#{table}.#{field} <= '%s'" % [self.class.connection.quoted_date(to)]) | |
|
847 | 847 | end |
|
848 | 848 | s.join(' AND ') |
|
849 | 849 | end |
@@ -25,7 +25,7 class Repository < ActiveRecord::Base | |||
|
25 | 25 | IDENTIFIER_MAX_LENGTH = 255 |
|
26 | 26 | |
|
27 | 27 | belongs_to :project |
|
28 |
has_many :changesets, |
|
|
28 | has_many :changesets, lambda{order("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC")} | |
|
29 | 29 | has_many :filechanges, :class_name => 'Change', :through => :changesets |
|
30 | 30 | |
|
31 | 31 | serialize :extra_info |
@@ -45,6 +45,7 class Repository < ActiveRecord::Base | |||
|
45 | 45 | validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true |
|
46 | 46 | # Checks if the SCM is enabled when creating a repository |
|
47 | 47 | validate :repo_create_validation, :on => :create |
|
48 | attr_protected :id | |
|
48 | 49 | |
|
49 | 50 | safe_attributes 'identifier', |
|
50 | 51 | 'login', |
@@ -264,7 +265,7 class Repository < ActiveRecord::Base | |||
|
264 | 265 | reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"). |
|
265 | 266 | limit(limit). |
|
266 | 267 | preload(:user). |
|
267 |
a |
|
|
268 | to_a | |
|
268 | 269 | else |
|
269 | 270 | filechanges. |
|
270 | 271 | where("path = ?", path.with_leading_slash). |
@@ -313,7 +314,8 class Repository < ActiveRecord::Base | |||
|
313 | 314 | return @found_committer_users[committer] if @found_committer_users.has_key?(committer) |
|
314 | 315 | |
|
315 | 316 | user = nil |
|
316 |
c = changesets.where(:committer => committer). |
|
|
317 | c = changesets.where(:committer => committer). | |
|
318 | includes(:user).references(:user).first | |
|
317 | 319 | if c && c.user |
|
318 | 320 | user = c.user |
|
319 | 321 | elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/ |
@@ -484,10 +486,10 class Repository < ActiveRecord::Base | |||
|
484 | 486 | ci = "#{table_name_prefix}changesets_issues#{table_name_suffix}" |
|
485 | 487 | cp = "#{table_name_prefix}changeset_parents#{table_name_suffix}" |
|
486 | 488 | |
|
487 | connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") | |
|
488 | connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") | |
|
489 | connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") | |
|
490 | connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}") | |
|
489 | self.class.connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") | |
|
490 | self.class.connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") | |
|
491 | self.class.connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})") | |
|
492 | self.class.connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}") | |
|
491 | 493 | clear_extra_info_of_changesets |
|
492 | 494 | end |
|
493 | 495 |
@@ -199,7 +199,7 class Repository::Cvs < Repository | |||
|
199 | 199 | # Need to retrieve existing revision numbers to sort them as integers |
|
200 | 200 | sql = "SELECT revision FROM #{Changeset.table_name} " |
|
201 | 201 | sql << "WHERE repository_id = #{id} AND revision NOT LIKE 'tmp%'" |
|
202 | @current_revision_number ||= (connection.select_values(sql).collect(&:to_i).max || 0) | |
|
202 | @current_revision_number ||= (self.class.connection.select_values(sql).collect(&:to_i).max || 0) | |
|
203 | 203 | @current_revision_number += 1 |
|
204 | 204 | end |
|
205 | 205 | end |
@@ -241,7 +241,7 class Repository::Git < Repository | |||
|
241 | 241 | def latest_changesets(path,rev,limit=10) |
|
242 | 242 | revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false) |
|
243 | 243 | return [] if revisions.nil? || revisions.empty? |
|
244 |
changesets.where(:scmid => revisions.map {|c| c.scmid}).a |
|
|
244 | changesets.where(:scmid => revisions.map {|c| c.scmid}).to_a | |
|
245 | 245 | end |
|
246 | 246 | |
|
247 | 247 | def clear_extra_info_of_changesets |
@@ -20,7 +20,7 require 'redmine/scm/adapters/mercurial_adapter' | |||
|
20 | 20 | class Repository::Mercurial < Repository |
|
21 | 21 | # sort changesets by revision number |
|
22 | 22 | has_many :changesets, |
|
23 |
|
|
|
23 | lambda {order("#{Changeset.table_name}.id DESC")}, | |
|
24 | 24 | :foreign_key => 'repository_id' |
|
25 | 25 | |
|
26 | 26 | attr_protected :root_url |
@@ -117,9 +117,10 class Repository::Mercurial < Repository | |||
|
117 | 117 | changesets. |
|
118 | 118 | includes(:user). |
|
119 | 119 | where(latest_changesets_cond(path, rev, limit)). |
|
120 | references(:user). | |
|
120 | 121 | limit(limit). |
|
121 | 122 | order("#{Changeset.table_name}.id DESC"). |
|
122 |
a |
|
|
123 | to_a | |
|
123 | 124 | end |
|
124 | 125 | |
|
125 | 126 | def is_short_id_in_db? |
@@ -42,7 +42,7 class Repository::Subversion < Repository | |||
|
42 | 42 | revisions = scm.revisions(path, rev, nil, :limit => limit) |
|
43 | 43 | if revisions |
|
44 | 44 | identifiers = revisions.collect(&:identifier).compact |
|
45 |
changesets.where(:revision => identifiers).reorder("committed_on DESC").includes(:repository, :user).a |
|
|
45 | changesets.where(:revision => identifiers).reorder("committed_on DESC").includes(:repository, :user).to_a | |
|
46 | 46 | else |
|
47 | 47 | [] |
|
48 | 48 | end |
@@ -166,7 +166,7 class Role < ActiveRecord::Base | |||
|
166 | 166 | |
|
167 | 167 | # Find all the roles that can be given to a project member |
|
168 | 168 | def self.find_all_givable |
|
169 |
Role.givable.a |
|
|
169 | Role.givable.to_a | |
|
170 | 170 | end |
|
171 | 171 | |
|
172 | 172 | # Return the builtin 'non member' role. If the role doesn't exist, |
@@ -86,6 +86,7 class Setting < ActiveRecord::Base | |||
|
86 | 86 | validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| |
|
87 | 87 | (s = @@available_settings[setting.name]) && s['format'] == 'int' |
|
88 | 88 | } |
|
89 | attr_protected :id | |
|
89 | 90 | |
|
90 | 91 | # Hash used to cache setting values |
|
91 | 92 | @cached_settings = {} |
@@ -142,6 +143,7 END_SRC | |||
|
142 | 143 | def self.set_from_params(name, params) |
|
143 | 144 | params = params.dup |
|
144 | 145 | params.delete_if {|v| v.blank? } if params.is_a?(Array) |
|
146 | params.symbolize_keys! if params.is_a?(Hash) | |
|
145 | 147 | |
|
146 | 148 | m = "#{name}_from_params" |
|
147 | 149 | if respond_to? m |
@@ -35,7 +35,7 class TimeEntry < ActiveRecord::Base | |||
|
35 | 35 | |
|
36 | 36 | acts_as_activity_provider :timestamp => "#{table_name}.created_on", |
|
37 | 37 | :author_key => :user_id, |
|
38 |
: |
|
|
38 | :scope => preload(:project) | |
|
39 | 39 | |
|
40 | 40 | validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on |
|
41 | 41 | validates_numericality_of :hours, :allow_nil => true, :message => :invalid |
@@ -45,13 +45,19 class TimeEntry < ActiveRecord::Base | |||
|
45 | 45 | validate :validate_time_entry |
|
46 | 46 | |
|
47 | 47 | scope :visible, lambda {|*args| |
|
48 | includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_time_entries, *args)) | |
|
48 | joins(:project). | |
|
49 | references(:project). | |
|
50 | where(Project.allowed_to_condition(args.shift || User.current, :view_time_entries, *args)) | |
|
49 | 51 | } |
|
50 | 52 | scope :on_issue, lambda {|issue| |
|
51 | includes(:issue).where("#{Issue.table_name}.root_id = #{issue.root_id} AND #{Issue.table_name}.lft >= #{issue.lft} AND #{Issue.table_name}.rgt <= #{issue.rgt}") | |
|
53 | joins(:issue). | |
|
54 | references(:issue). | |
|
55 | where("#{Issue.table_name}.root_id = #{issue.root_id} AND #{Issue.table_name}.lft >= #{issue.lft} AND #{Issue.table_name}.rgt <= #{issue.rgt}") | |
|
52 | 56 | } |
|
53 | 57 | scope :on_project, lambda {|project, include_subprojects| |
|
54 | includes(:project).where(project.project_condition(include_subprojects)) | |
|
58 | joins(:project). | |
|
59 | references(:project). | |
|
60 | where(project.project_condition(include_subprojects)) | |
|
55 | 61 | } |
|
56 | 62 | scope :spent_between, lambda {|from, to| |
|
57 | 63 | if from && to |
@@ -42,7 +42,7 class TimeEntryQuery < Query | |||
|
42 | 42 | if project |
|
43 | 43 | principals += project.principals.sort |
|
44 | 44 | unless project.leaf? |
|
45 |
subprojects = project.descendants.visible.a |
|
|
45 | subprojects = project.descendants.visible.to_a | |
|
46 | 46 | if subprojects.any? |
|
47 | 47 | add_available_filter "subproject_id", |
|
48 | 48 | :type => :list_subprojects, |
@@ -109,7 +109,8 class TimeEntryQuery < Query | |||
|
109 | 109 | where(statement). |
|
110 | 110 | order(order_option). |
|
111 | 111 | joins(joins_for_order_statement(order_option.join(','))). |
|
112 | includes(:activity) | |
|
112 | includes(:activity). | |
|
113 | references(:activity) | |
|
113 | 114 | end |
|
114 | 115 | |
|
115 | 116 | def sql_for_activity_id_field(field, operator, value) |
@@ -18,6 +18,7 | |||
|
18 | 18 | class Token < ActiveRecord::Base |
|
19 | 19 | belongs_to :user |
|
20 | 20 | validates_uniqueness_of :value |
|
21 | attr_protected :id | |
|
21 | 22 | |
|
22 | 23 | before_create :delete_previous_tokens, :generate_new_token |
|
23 | 24 |
@@ -63,7 +63,7 class Tracker < ActiveRecord::Base | |||
|
63 | 63 | connection.select_rows("SELECT DISTINCT old_status_id, new_status_id FROM #{WorkflowTransition.table_name} WHERE tracker_id = #{id} AND type = 'WorkflowTransition'"). |
|
64 | 64 | flatten. |
|
65 | 65 | uniq |
|
66 |
@issue_statuses = IssueStatus.where(:id => ids).a |
|
|
66 | @issue_statuses = IssueStatus.where(:id => ids).to_a.sort | |
|
67 | 67 | end |
|
68 | 68 | |
|
69 | 69 | def disabled_core_fields |
@@ -92,7 +92,7 class Tracker < ActiveRecord::Base | |||
|
92 | 92 | # Returns the fields that are disabled for all the given trackers |
|
93 | 93 | def self.disabled_core_fields(trackers) |
|
94 | 94 | if trackers.present? |
|
95 |
trackers |
|
|
95 | trackers.map(&:disabled_core_fields).reduce(:&) | |
|
96 | 96 | else |
|
97 | 97 | [] |
|
98 | 98 | end |
@@ -79,8 +79,8 class User < Principal | |||
|
79 | 79 | :after_remove => Proc.new {|user, group| group.user_removed(user)} |
|
80 | 80 | has_many :changesets, :dependent => :nullify |
|
81 | 81 | has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' |
|
82 | has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'" | |
|
83 | has_one :api_token, :class_name => 'Token', :conditions => "action='api'" | |
|
82 | has_one :rss_token, lambda {where "action='feeds'"}, :class_name => 'Token' | |
|
83 | has_one :api_token, lambda {where "action='api'"}, :class_name => 'Token' | |
|
84 | 84 | belongs_to :auth_source |
|
85 | 85 | |
|
86 | 86 | scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") } |
@@ -105,9 +105,13 class User < Principal | |||
|
105 | 105 | validates_length_of :firstname, :lastname, :maximum => 30 |
|
106 | 106 | validates_format_of :mail, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true |
|
107 | 107 | validates_length_of :mail, :maximum => MAIL_LENGTH_LIMIT, :allow_nil => true |
|
108 | validates_confirmation_of :password, :allow_nil => true | |
|
109 | 108 | validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true |
|
110 | 109 | validate :validate_password_length |
|
110 | validate do | |
|
111 | if password_confirmation && password != password_confirmation | |
|
112 | errors.add(:password, :confirmation) | |
|
113 | end | |
|
114 | end | |
|
111 | 115 | |
|
112 | 116 | before_create :set_mail_notification |
|
113 | 117 | before_save :generate_password_if_needed, :update_hashed_password |
@@ -151,6 +155,15 class User < Principal | |||
|
151 | 155 | write_attribute(:mail, arg.to_s.strip) |
|
152 | 156 | end |
|
153 | 157 | |
|
158 | def self.find_or_initialize_by_identity_url(url) | |
|
159 | user = where(:identity_url => url).first | |
|
160 | unless user | |
|
161 | user = User.new | |
|
162 | user.identity_url = url | |
|
163 | end | |
|
164 | user | |
|
165 | end | |
|
166 | ||
|
154 | 167 | def identity_url=(url) |
|
155 | 168 | if url.blank? |
|
156 | 169 | write_attribute(:identity_url, '') |
@@ -496,10 +509,12 class User < Principal | |||
|
496 | 509 | |
|
497 | 510 | hash = Hash.new([]) |
|
498 | 511 | |
|
499 | members = Member.joins(:project). | |
|
512 | group_class = anonymous? ? GroupAnonymous : GroupNonMember | |
|
513 | members = Member.joins(:project, :principal). | |
|
500 | 514 | where("#{Project.table_name}.status <> 9"). |
|
501 |
where("#{Member.table_name}.user_id = ? OR (#{Project.table_name}.is_public = ? AND #{ |
|
|
502 | preload(:project, :roles) | |
|
515 | where("#{Member.table_name}.user_id = ? OR (#{Project.table_name}.is_public = ? AND #{Principal.table_name}.type = ?)", self.id, true, group_class.name). | |
|
516 | preload(:project, :roles). | |
|
517 | to_a | |
|
503 | 518 | |
|
504 | 519 | members.reject! {|member| member.user_id != id && project_ids.include?(member.project_id)} |
|
505 | 520 | members.each do |member| |
@@ -558,6 +573,8 class User < Principal | |||
|
558 | 573 | # Authorize if user is authorized on every element of the array |
|
559 | 574 | context.map {|project| allowed_to?(action, project, options, &block)}.reduce(:&) |
|
560 | 575 | end |
|
576 | elsif context | |
|
577 | raise ArgumentError.new("#allowed_to? context argument must be a Project, an Array of projects or nil") | |
|
561 | 578 | elsif options[:global] |
|
562 | 579 | # Admin users are always authorized |
|
563 | 580 | return true if admin? |
@@ -710,17 +727,17 class User < Principal | |||
|
710 | 727 | return if self.id.nil? |
|
711 | 728 | |
|
712 | 729 | substitute = User.anonymous |
|
713 | Attachment.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) | |
|
730 | Attachment.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) | |
|
714 | 731 | Comment.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
|
715 | 732 | Issue.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
|
716 | 733 | Issue.where(['assigned_to_id = ?', id]).update_all('assigned_to_id = NULL') |
|
717 | Journal.where(['user_id = ?', id]).update_all(['user_id = ?', substitute.id]) | |
|
734 | Journal.where(['user_id = ?', id]).update_all(['user_id = ?', substitute.id]) | |
|
718 | 735 | JournalDetail. |
|
719 | 736 | where(["property = 'attr' AND prop_key = 'assigned_to_id' AND old_value = ?", id.to_s]). |
|
720 | 737 | update_all(['old_value = ?', substitute.id.to_s]) |
|
721 | 738 | JournalDetail. |
|
722 | 739 | where(["property = 'attr' AND prop_key = 'assigned_to_id' AND value = ?", id.to_s]). |
|
723 | update_all(['value = ?', substitute.id.to_s]) | |
|
740 | update_all(['value = ?', substitute.id.to_s]) | |
|
724 | 741 | Message.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
|
725 | 742 | News.where(['author_id = ?', id]).update_all(['author_id = ?', substitute.id]) |
|
726 | 743 | # Remove private queries and keep public ones |
@@ -33,11 +33,14 class Version < ActiveRecord::Base | |||
|
33 | 33 | validates :effective_date, :date => true |
|
34 | 34 | validates_inclusion_of :status, :in => VERSION_STATUSES |
|
35 | 35 | validates_inclusion_of :sharing, :in => VERSION_SHARINGS |
|
36 | attr_protected :id | |
|
36 | 37 | |
|
37 | 38 | scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)} |
|
38 | 39 | scope :open, lambda { where(:status => 'open') } |
|
39 | 40 | scope :visible, lambda {|*args| |
|
40 | includes(:project).where(Project.allowed_to_condition(args.first || User.current, :view_issues)) | |
|
41 | joins(:project). | |
|
42 | references(:project). | |
|
43 | where(Project.allowed_to_condition(args.first || User.current, :view_issues)) | |
|
41 | 44 | } |
|
42 | 45 | |
|
43 | 46 | safe_attributes 'name', |
@@ -230,11 +233,6 class Version < ActiveRecord::Base | |||
|
230 | 233 | end |
|
231 | 234 | end |
|
232 | 235 | |
|
233 | # Returns true if the version is shared, otherwise false | |
|
234 | def shared? | |
|
235 | sharing != 'none' | |
|
236 | end | |
|
237 | ||
|
238 | 236 | private |
|
239 | 237 | |
|
240 | 238 | def load_issue_counts |
@@ -22,6 +22,7 class Watcher < ActiveRecord::Base | |||
|
22 | 22 | validates_presence_of :user |
|
23 | 23 | validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id] |
|
24 | 24 | validate :validate_user |
|
25 | attr_protected :id | |
|
25 | 26 | |
|
26 | 27 | # Returns true if at least one object among objects is watched by user |
|
27 | 28 | def self.any_watched?(objects, user) |
@@ -18,13 +18,14 | |||
|
18 | 18 | class Wiki < ActiveRecord::Base |
|
19 | 19 | include Redmine::SafeAttributes |
|
20 | 20 | belongs_to :project |
|
21 |
has_many :pages, :class_name => 'WikiPage', :dependent => :destroy |
|
|
21 | has_many :pages, lambda {order('title')}, :class_name => 'WikiPage', :dependent => :destroy | |
|
22 | 22 | has_many :redirects, :class_name => 'WikiRedirect', :dependent => :delete_all |
|
23 | 23 | |
|
24 | 24 | acts_as_watchable |
|
25 | 25 | |
|
26 | 26 | validates_presence_of :start_page |
|
27 | 27 | validates_format_of :start_page, :with => /\A[^,\.\/\?\;\|\:]*\z/ |
|
28 | attr_protected :id | |
|
28 | 29 | |
|
29 | 30 | safe_attributes 'start_page' |
|
30 | 31 |
@@ -23,6 +23,7 class WikiContent < ActiveRecord::Base | |||
|
23 | 23 | belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' |
|
24 | 24 | validates_presence_of :text |
|
25 | 25 | validates_length_of :comments, :maximum => 255, :allow_nil => true |
|
26 | attr_protected :id | |
|
26 | 27 | |
|
27 | 28 | acts_as_versioned |
|
28 | 29 | |
@@ -68,13 +69,13 class WikiContent < ActiveRecord::Base | |||
|
68 | 69 | :timestamp => "#{WikiContent.versioned_table_name}.updated_on", |
|
69 | 70 | :author_key => "#{WikiContent.versioned_table_name}.author_id", |
|
70 | 71 | :permission => :view_wiki_edits, |
|
71 |
: |
|
|
72 |
|
|
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
|
76 |
|
|
|
77 |
|
|
|
72 | :scope => select("#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comments, " + | |
|
73 | "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title, " + | |
|
74 | "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " + | |
|
75 | "#{WikiContent.versioned_table_name}.id"). | |
|
76 | joins("LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " + | |
|
77 | "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " + | |
|
78 | "LEFT JOIN #{Project.table_name} ON #{Project.table_name}.id = #{Wiki.table_name}.project_id") | |
|
78 | 79 | |
|
79 | 80 | after_destroy :page_update_after_destroy |
|
80 | 81 | |
@@ -104,7 +105,7 class WikiContent < ActiveRecord::Base | |||
|
104 | 105 | # uncompressed data |
|
105 | 106 | data |
|
106 | 107 | end |
|
107 |
str.force_encoding("UTF-8") |
|
|
108 | str.force_encoding("UTF-8") | |
|
108 | 109 | str |
|
109 | 110 | end |
|
110 | 111 | end |
@@ -33,7 +33,7 class WikiPage < ActiveRecord::Base | |||
|
33 | 33 | :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}} |
|
34 | 34 | |
|
35 | 35 | acts_as_searchable :columns => ['title', "#{WikiContent.table_name}.text"], |
|
36 |
: |
|
|
36 | :scope => preload(:wiki => :project).joins(:content, {:wiki => :project}), | |
|
37 | 37 | :permission => :view_wiki_pages, |
|
38 | 38 | :project_key => "#{Wiki.table_name}.project_id" |
|
39 | 39 | |
@@ -43,6 +43,7 class WikiPage < ActiveRecord::Base | |||
|
43 | 43 | validates_format_of :title, :with => /\A[^,\.\/\?\;\|\s]*\z/ |
|
44 | 44 | validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false |
|
45 | 45 | validates_associated :content |
|
46 | attr_protected :id | |
|
46 | 47 | |
|
47 | 48 | validate :validate_parent_title |
|
48 | 49 | before_destroy :remove_redirects |
@@ -180,12 +181,10 class WikiPage < ActiveRecord::Base | |||
|
180 | 181 | def save_with_content(content) |
|
181 | 182 | ret = nil |
|
182 | 183 | transaction do |
|
183 | self.content = content | |
|
184 | if new_record? | |
|
185 | # Rails automatically saves associated content | |
|
186 | ret = save | |
|
187 | else | |
|
188 | ret = save && (content.text_changed? ? content.save : true) | |
|
184 | ret = save | |
|
185 | if content.text_changed? | |
|
186 | self.content = content | |
|
187 | ret = ret && content.changed? | |
|
189 | 188 | end |
|
190 | 189 | raise ActiveRecord::Rollback unless ret |
|
191 | 190 | end |
@@ -20,4 +20,5 class WikiRedirect < ActiveRecord::Base | |||
|
20 | 20 | |
|
21 | 21 | validates_presence_of :title, :redirects_to |
|
22 | 22 | validates_length_of :title, :redirects_to, :maximum => 255 |
|
23 | attr_protected :id | |
|
23 | 24 | end |
@@ -24,6 +24,7 class WorkflowRule < ActiveRecord::Base | |||
|
24 | 24 | belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id' |
|
25 | 25 | |
|
26 | 26 | validates_presence_of :role, :tracker, :old_status |
|
27 | attr_protected :id | |
|
27 | 28 | |
|
28 | 29 | # Copies workflows from source to targets |
|
29 | 30 | def self.copy(source_tracker, source_role, target_trackers, target_roles) |
@@ -34,7 +35,7 class WorkflowRule < ActiveRecord::Base | |||
|
34 | 35 | target_trackers = [target_trackers].flatten.compact |
|
35 | 36 | target_roles = [target_roles].flatten.compact |
|
36 | 37 | |
|
37 |
target_trackers = Tracker.sorted.a |
|
|
38 | target_trackers = Tracker.sorted.to_a if target_trackers.empty? | |
|
38 | 39 | target_roles = Role.all if target_roles.empty? |
|
39 | 40 | |
|
40 | 41 | target_trackers.each do |target_tracker| |
@@ -40,7 +40,7 class WorkflowTransition < WorkflowRule | |||
|
40 | 40 | roles = Array.wrap roles |
|
41 | 41 | |
|
42 | 42 | transaction do |
|
43 |
records = WorkflowTransition.where(:tracker_id => trackers.map(&:id), :role_id => roles.map(&:id)).a |
|
|
43 | records = WorkflowTransition.where(:tracker_id => trackers.map(&:id), :role_id => roles.map(&:id)).to_a | |
|
44 | 44 | |
|
45 | 45 | transitions.each do |old_status_id, transitions_by_new_status| |
|
46 | 46 | transitions_by_new_status.each do |new_status_id, transition_by_rule| |
@@ -8,8 +8,8 | |||
|
8 | 8 | <% end -%> |
|
9 | 9 | </ul> |
|
10 | 10 | <div class="tabs-buttons" style="display:none;"> |
|
11 |
<button class="tab-left" |
|
|
12 |
<button class="tab-right" |
|
|
11 | <button class="tab-left" onclick="moveTabLeft(this); return false;"></button> | |
|
12 | <button class="tab-right" onclick="moveTabRight(this); return false;"></button> | |
|
13 | 13 | </div> |
|
14 | 14 | </div> |
|
15 | 15 |
@@ -1,5 +1,5 | |||
|
1 | 1 | <% roles = Role.find_all_givable %> |
|
2 |
<% projects = Project.active.a |
|
|
2 | <% projects = Project.active.to_a %> | |
|
3 | 3 | |
|
4 | 4 | <div class="splitcontentleft"> |
|
5 | 5 | <% if @group.memberships.any? %> |
@@ -1,6 +1,6 | |||
|
1 | 1 | <%= error_messages_for 'member' %> |
|
2 | 2 | <% roles = Role.find_all_givable |
|
3 |
members = @project.member_principals.includes(:member_roles, :roles, :principal).a |
|
|
3 | members = @project.member_principals.includes(:member_roles, :roles, :principal).to_a.sort %> | |
|
4 | 4 | |
|
5 | 5 | <div class="splitcontentleft"> |
|
6 | 6 | <% if members.any? %> |
@@ -8,7 +8,7 | |||
|
8 | 8 | <% elsif params[:issue_id] %> |
|
9 | 9 | <%= hidden_field_tag 'issue_id', params[:issue_id] %> |
|
10 | 10 | <% else %> |
|
11 |
<p><%= f.select :project_id, project_tree_options_for_select(Project.allowed_to(:log_time).a |
|
|
11 | <p><%= f.select :project_id, project_tree_options_for_select(Project.allowed_to(:log_time).to_a, :selected => @time_entry.project, :include_blank => true) %></p> | |
|
12 | 12 | <% end %> |
|
13 | 13 | <% end %> |
|
14 | 14 | <p> |
@@ -1,5 +1,5 | |||
|
1 | 1 | <% roles = Role.find_all_givable %> |
|
2 |
<% projects = Project.active.a |
|
|
2 | <% projects = Project.active.to_a %> | |
|
3 | 3 | |
|
4 | 4 | <div class="splitcontentleft"> |
|
5 | 5 | <% if @user.memberships.any? %> |
@@ -23,7 +23,7 | |||
|
23 | 23 | <%= fp.select :parent_id, |
|
24 | 24 | content_tag('option', '', :value => '') + |
|
25 | 25 | wiki_page_options_for_select( |
|
26 |
@wiki.pages.includes(:parent).a |
|
|
26 | @wiki.pages.includes(:parent).to_a - | |
|
27 | 27 | @page.self_and_descendants, @page.parent) %> |
|
28 | 28 | </p> |
|
29 | 29 | <% end %> |
@@ -13,7 +13,7 | |||
|
13 | 13 | <p><%= f.select :parent_id, |
|
14 | 14 | content_tag('option', '', :value => '') + |
|
15 | 15 | wiki_page_options_for_select( |
|
16 |
@wiki.pages.includes(:parent).a |
|
|
16 | @wiki.pages.includes(:parent).to_a - @page.self_and_descendants, | |
|
17 | 17 | @page.parent), |
|
18 | 18 | :label => :field_parent_title %></p> |
|
19 | 19 | </div> |
@@ -2,12 +2,7 require File.expand_path('../boot', __FILE__) | |||
|
2 | 2 | |
|
3 | 3 | require 'rails/all' |
|
4 | 4 | |
|
5 | if defined?(Bundler) | |
|
6 | # If you precompile assets before deploying to production, use this line | |
|
7 | Bundler.require(*Rails.groups(:assets => %w(development test))) | |
|
8 | # If you want your assets lazily compiled in production, use this line | |
|
9 | # Bundler.require(:default, :assets, Rails.env) | |
|
10 | end | |
|
5 | Bundler.require(*Rails.groups) | |
|
11 | 6 | |
|
12 | 7 | module RedmineApp |
|
13 | 8 | class Application < Rails::Application |
@@ -33,7 +28,7 module RedmineApp | |||
|
33 | 28 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] |
|
34 | 29 | # config.i18n.default_locale = :de |
|
35 | 30 | |
|
36 |
I18n.enforce_available_locales = |
|
|
31 | I18n.enforce_available_locales = true | |
|
37 | 32 | |
|
38 | 33 | # Configure the default encoding used in templates for Ruby 1.9. |
|
39 | 34 | config.encoding = "utf-8" |
@@ -1,5 +1,3 | |||
|
1 | require 'rubygems' | |
|
2 | ||
|
3 | 1 |
|
|
4 | 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) |
|
5 | 3 |
@@ -1,5 +1,4 | |||
|
1 |
# Default setup is given for MySQL with ruby1.9. |
|
|
2 | # with MySQL and ruby1.8, replace the adapter name with `mysql`. | |
|
1 | # Default setup is given for MySQL with ruby1.9. | |
|
3 | 2 | # Examples for PostgreSQL, SQLite3 and SQL Server can be found at the end. |
|
4 | 3 | # Line indentation must be 2 spaces (no tabs). |
|
5 | 4 |
@@ -1,4 +1,4 | |||
|
1 |
# Load the |
|
|
1 | # Load the Rails application | |
|
2 | 2 | require File.expand_path('../application', __FILE__) |
|
3 | 3 | |
|
4 | 4 | # Make sure there's no plugin in vendor/plugin before starting |
@@ -10,5 +10,5 if Dir.glob(File.join(vendor_plugins_dir, "*")).any? | |||
|
10 | 10 | exit 1 |
|
11 | 11 | end |
|
12 | 12 | |
|
13 |
# Initialize the |
|
|
14 |
R |
|
|
13 | # Initialize the Rails application | |
|
14 | Rails.application.initialize! |
@@ -1,19 +1,21 | |||
|
1 | # Settings specified here will take precedence over those in config/application.rb | |
|
2 | RedmineApp::Application.configure do | |
|
1 | Rails.application.configure do | |
|
2 | # Settings specified here will take precedence over those in config/application.rb | |
|
3 | ||
|
3 | 4 | # In the development environment your application's code is reloaded on |
|
4 | 5 | # every request. This slows down response time but is perfect for development |
|
5 | 6 | # since you don't have to restart the webserver when you make code changes. |
|
6 |
config.cache_classes |
|
|
7 | config.cache_classes = false | |
|
7 | 8 | |
|
8 | # Log error messages when you accidentally call methods on nil. | |
|
9 | config.whiny_nils = true | |
|
9 | # Do not eager load code on boot. | |
|
10 | config.eager_load = false | |
|
10 | 11 | |
|
11 | 12 | # Show full error reports and disable caching |
|
12 |
|
|
|
13 |
config.action_controller.perform_caching |
|
|
13 | config.consider_all_requests_local = true | |
|
14 | config.action_controller.perform_caching = false | |
|
14 | 15 | |
|
15 | # Don't care if the mailer can't send | |
|
16 | # Disable delivery errors | |
|
16 | 17 | config.action_mailer.raise_delivery_errors = false |
|
17 | 18 | |
|
19 | # Print deprecation notices to stderr and the Rails logger. | |
|
18 | 20 | config.active_support.deprecation = [:stderr, :log] |
|
19 | 21 | end |
@@ -1,33 +1,25 | |||
|
1 | # Settings specified here will take precedence over those in config/application.rb | |
|
2 | RedmineApp::Application.configure do | |
|
3 | # The production environment is meant for finished, "live" apps. | |
|
4 | # Code is not reloaded between requests | |
|
1 | Rails.application.configure do | |
|
2 | # Settings specified here will take precedence over those in config/application.rb | |
|
3 | ||
|
4 | # Code is not reloaded between requests. | |
|
5 | 5 | config.cache_classes = true |
|
6 | 6 | |
|
7 | ##### | |
|
8 | # Customize the default logger | |
|
9 | # http://www.ruby-doc.org/stdlib-1.8.7/libdoc/logger/rdoc/Logger.html | |
|
10 | # | |
|
11 | # Use a different logger for distributed setups | |
|
12 | # config.logger = SyslogLogger.new | |
|
13 | # | |
|
14 | # Rotate logs bigger than 1MB, keeps no more than 7 rotated logs around. | |
|
15 | # When setting a new Logger, make sure to set it's log level too. | |
|
16 | # | |
|
17 | # config.logger = Logger.new(config.log_path, 7, 1048576) | |
|
18 | # config.logger.level = Logger::INFO | |
|
7 | # Eager load code on boot. This eager loads most of Rails and | |
|
8 | # your application in memory, allowing both threaded web servers | |
|
9 | # and those relying on copy on write to perform better. | |
|
10 | # Rake tasks automatically ignore this option for performance. | |
|
11 | config.eager_load = true | |
|
19 | 12 | |
|
20 | # Full error reports are disabled and caching is turned on | |
|
13 | # Full error reports are disabled and caching is turned on. | |
|
14 | config.consider_all_requests_local = false | |
|
21 | 15 | config.action_controller.perform_caching = true |
|
22 | 16 | |
|
23 | # Enable serving of images, stylesheets, and javascripts from an asset server | |
|
24 | # config.action_controller.asset_host = "http://assets.example.com" | |
|
25 | ||
|
26 | # Disable delivery errors if you bad email addresses should just be ignored | |
|
17 | # Disable delivery errors | |
|
27 | 18 | config.action_mailer.raise_delivery_errors = false |
|
28 | 19 | |
|
29 | 20 | # No email in production log |
|
30 | 21 | config.action_mailer.logger = nil |
|
31 | 22 | |
|
23 | # Print deprecation notices to the Rails logger. | |
|
32 | 24 | config.active_support.deprecation = :log |
|
33 | 25 | end |
@@ -1,16 +1,19 | |||
|
1 | # Settings specified here will take precedence over those in config/application.rb | |
|
2 | RedmineApp::Application.configure do | |
|
1 | Rails.application.configure do | |
|
2 | # Settings specified here will take precedence over those in config/application.rb | |
|
3 | ||
|
3 | 4 | # The test environment is used exclusively to run your application's |
|
4 | 5 | # test suite. You never need to work with it otherwise. Remember that |
|
5 | 6 | # your test database is "scratch space" for the test suite and is wiped |
|
6 | 7 | # and recreated between test runs. Don't rely on the data there! |
|
7 | 8 | config.cache_classes = true |
|
8 | 9 | |
|
9 | # Log error messages when you accidentally call methods on nil. | |
|
10 | config.whiny_nils = true | |
|
10 | # Do not eager load code on boot. This avoids loading your whole application | |
|
11 | # just for the purpose of running a single test. If you are using a tool that | |
|
12 | # preloads Rails for running tests, you may have to set it to true. | |
|
13 | config.eager_load = false | |
|
11 | 14 | |
|
12 | 15 | # Show full error reports and disable caching |
|
13 |
|
|
|
16 | config.consider_all_requests_local = true | |
|
14 | 17 | config.action_controller.perform_caching = false |
|
15 | 18 | |
|
16 | 19 | config.action_mailer.perform_deliveries = true |
@@ -20,10 +23,10 RedmineApp::Application.configure do | |||
|
20 | 23 | # ActionMailer::Base.deliveries array. |
|
21 | 24 | config.action_mailer.delivery_method = :test |
|
22 | 25 | |
|
23 | # Skip protect_from_forgery in requests | |
|
24 | # http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application | |
|
26 | # Disable request forgery protection in test environment. | |
|
25 | 27 | config.action_controller.allow_forgery_protection = false |
|
26 | 28 | |
|
29 | # Print deprecation notices to stderr and the Rails logger. | |
|
27 | 30 | config.active_support.deprecation = [:stderr, :log] |
|
28 | 31 | |
|
29 | 32 | config.secret_token = 'a secret token for running the tests' |
@@ -1,1 +1,2 | |||
|
1 | # Same as test.rb | |
|
1 | 2 | instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb')) |
@@ -1,1 +1,2 | |||
|
1 | # Same as test.rb | |
|
1 | 2 | instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb')) |
@@ -54,56 +54,23 module ActionView | |||
|
54 | 54 | end |
|
55 | 55 | end |
|
56 | 56 | |
|
57 | # Do not HTML escape text templates | |
|
58 | module ActionView | |
|
59 | class Template | |
|
60 | module Handlers | |
|
61 | class ERB | |
|
62 | def call(template) | |
|
63 | if template.source.encoding_aware? | |
|
64 | # First, convert to BINARY, so in case the encoding is | |
|
65 | # wrong, we can still find an encoding tag | |
|
66 | # (<%# encoding %>) inside the String using a regular | |
|
67 | # expression | |
|
68 | template_source = template.source.dup.force_encoding("BINARY") | |
|
69 | ||
|
70 | erb = template_source.gsub(ENCODING_TAG, '') | |
|
71 | encoding = $2 | |
|
72 | ||
|
73 | erb.force_encoding valid_encoding(template.source.dup, encoding) | |
|
74 | ||
|
75 | # Always make sure we return a String in the default_internal | |
|
76 | erb.encode! | |
|
77 | else | |
|
78 | erb = template.source.dup | |
|
79 | end | |
|
80 | ||
|
81 | self.class.erb_implementation.new( | |
|
82 | erb, | |
|
83 | :trim => (self.class.erb_trim_mode == "-"), | |
|
84 | :escape => template.identifier =~ /\.text/ # only escape HTML templates | |
|
85 | ).src | |
|
86 | end | |
|
87 | end | |
|
88 | end | |
|
89 | end | |
|
90 | end | |
|
91 | ||
|
92 | 57 | ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe } |
|
93 | 58 | |
|
94 | 59 | # HTML5: <option value=""></option> is invalid, use <option value=""> </option> instead |
|
95 | 60 | module ActionView |
|
96 | 61 | module Helpers |
|
97 | class InstanceTag | |
|
98 | private | |
|
99 | def add_options_with_non_empty_blank_option(option_tags, options, value = nil) | |
|
100 | if options[:include_blank] == true | |
|
101 | options = options.dup | |
|
102 | options[:include_blank] = ' '.html_safe | |
|
62 | module Tags | |
|
63 | class Base | |
|
64 | private | |
|
65 | def add_options_with_non_empty_blank_option(option_tags, options, value = nil) | |
|
66 | if options[:include_blank] == true | |
|
67 | options = options.dup | |
|
68 | options[:include_blank] = ' '.html_safe | |
|
69 | end | |
|
70 | add_options_without_non_empty_blank_option(option_tags, options, value) | |
|
103 | 71 | end |
|
104 | add_options_without_non_empty_blank_option(option_tags, options, value) | |
|
72 | alias_method_chain :add_options, :non_empty_blank_option | |
|
105 | 73 | end |
|
106 | alias_method_chain :add_options, :non_empty_blank_option | |
|
107 | 74 | end |
|
108 | 75 | |
|
109 | 76 | module FormTagHelper |
@@ -1,5 +1,7 | |||
|
1 | 1 | I18n.default_locale = 'en' |
|
2 | 2 | I18n.backend = Redmine::I18n::Backend.new |
|
3 | # Forces I18n to load available locales from the backend | |
|
4 | I18n.config.available_locales = nil | |
|
3 | 5 | |
|
4 | 6 | require 'redmine' |
|
5 | 7 | |
@@ -20,9 +22,3 Redmine::Plugin.load | |||
|
20 | 22 | unless Redmine::Configuration['mirror_plugins_assets_on_startup'] == false |
|
21 | 23 | Redmine::Plugin.mirror_assets |
|
22 | 24 | end |
|
23 | ||
|
24 | Rails.application.config.to_prepare do | |
|
25 | Redmine::FieldFormat::RecordList.subclasses.each do |klass| | |
|
26 | klass.instance.reset_target_class | |
|
27 | end | |
|
28 | end No newline at end of file |
@@ -249,8 +249,8 ja: | |||
|
249 | 249 | field_is_for_all: 全プロジェクト向け |
|
250 | 250 | field_possible_values: 選択肢 |
|
251 | 251 | field_regexp: 正規表現 |
|
252 |
field_min_length: 最 |
|
|
253 |
field_max_length: 最大 |
|
|
252 | field_min_length: 最小値 | |
|
253 | field_max_length: 最大値 | |
|
254 | 254 | field_value: 値 |
|
255 | 255 | field_category: カテゴリ |
|
256 | 256 | field_title: タイトル |
@@ -305,7 +305,7 ja: | |||
|
305 | 305 | field_activity: 活動 |
|
306 | 306 | field_spent_on: 日付 |
|
307 | 307 | field_identifier: 識別子 |
|
308 |
field_is_filter: フィルタとして使 |
|
|
308 | field_is_filter: フィルタとして使う | |
|
309 | 309 | field_issue_to: 関連するチケット |
|
310 | 310 | field_delay: 遅延 |
|
311 | 311 | field_assignable: このロールにチケットを割り当て可能 |
@@ -314,7 +314,7 ja: | |||
|
314 | 314 | field_column_names: 項目 |
|
315 | 315 | field_time_entries: 時間を記録 |
|
316 | 316 | field_time_zone: タイムゾーン |
|
317 |
field_searchable: 検索 |
|
|
317 | field_searchable: 検索条件に設定可能とする | |
|
318 | 318 | field_default_value: デフォルト値 |
|
319 | 319 | field_comments_sorting: コメントの表示順 |
|
320 | 320 | field_parent_title: 親ページ |
@@ -541,7 +541,7 ja: | |||
|
541 | 541 | label_subproject_plural: サブプロジェクト |
|
542 | 542 | label_subproject_new: 新しいサブプロジェクト |
|
543 | 543 | label_and_its_subprojects: "%{value} とサブプロジェクト" |
|
544 |
label_min_max_length: 最 |
|
|
544 | label_min_max_length: 最小値 - 最大値の長さ | |
|
545 | 545 | label_list: リストから選択 |
|
546 | 546 | label_date: 日付 |
|
547 | 547 | label_integer: 整数 |
@@ -997,7 +997,6 | |||
|
997 | 997 | label_only: 僅於 |
|
998 | 998 | label_drop_down_list: 下拉式清單 |
|
999 | 999 | label_checkboxes: 核取方塊 |
|
1000 | label_radio_buttons: 選項按鈕 | |
|
1001 | 1000 | label_link_values_to: 連結欄位值至此網址 |
|
1002 | 1001 | label_custom_field_select_type: 請選擇連結此自訂欄位的物件類型 |
|
1003 | 1002 | label_check_for_updates: 檢查更新 |
@@ -1196,3 +1195,4 | |||
|
1196 | 1195 | description_date_from: 輸入起始日期 |
|
1197 | 1196 | description_date_to: 輸入結束日期 |
|
1198 | 1197 | text_repository_identifier_info: '僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線。<br />一旦儲存之後, 代碼便無法再次被更改。' |
|
1198 | label_radio_buttons: radio buttons |
@@ -15,7 +15,7 | |||
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 |
R |
|
|
18 | Rails.application.routes.draw do | |
|
19 | 19 | root :to => 'welcome#index', :as => 'home' |
|
20 | 20 | |
|
21 | 21 | match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post] |
@@ -25,10 +25,10 RedmineApp::Application.routes.draw do | |||
|
25 | 25 | match 'account/activate', :to => 'account#activate', :via => :get |
|
26 | 26 | get 'account/activation_email', :to => 'account#activation_email', :as => 'activation_email' |
|
27 | 27 | |
|
28 | match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put] | |
|
29 | match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put] | |
|
30 | match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put] | |
|
31 | match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put] | |
|
28 | match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put, :patch] | |
|
29 | match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put, :patch] | |
|
30 | match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put, :patch] | |
|
31 | match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put, :patch] | |
|
32 | 32 | |
|
33 | 33 | match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post |
|
34 | 34 | match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post] |
@@ -74,7 +74,7 RedmineApp::Application.routes.draw do | |||
|
74 | 74 | match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post |
|
75 | 75 | |
|
76 | 76 | resources :users |
|
77 | match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership' | |
|
77 | match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => [:put, :patch], :as => 'user_membership' | |
|
78 | 78 | match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete |
|
79 | 79 | match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships' |
|
80 | 80 | |
@@ -113,7 +113,7 RedmineApp::Application.routes.draw do | |||
|
113 | 113 | get 'issues/:copy_from/copy', :to => 'issues#new', :as => 'copy_issue' |
|
114 | 114 | resources :issues, :only => [:index, :new, :create] |
|
115 | 115 | # issue form update |
|
116 | match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :post], :as => 'issue_form' | |
|
116 | match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :patch, :post], :as => 'issue_form' | |
|
117 | 117 | |
|
118 | 118 | resources :files, :only => [:index, :new, :create] |
|
119 | 119 | |
@@ -151,7 +151,7 RedmineApp::Application.routes.draw do | |||
|
151 | 151 | post 'rename' |
|
152 | 152 | get 'history' |
|
153 | 153 | get 'diff' |
|
154 | match 'preview', :via => [:post, :put] | |
|
154 | match 'preview', :via => [:post, :put, :patch] | |
|
155 | 155 | post 'protect' |
|
156 | 156 | post 'add_attachment' |
|
157 | 157 | end |
@@ -17,7 +17,10 | |||
|
17 | 17 | |
|
18 | 18 | class Setup < ActiveRecord::Migration |
|
19 | 19 | |
|
20 |
class User < ActiveRecord::Base |
|
|
20 | class User < ActiveRecord::Base | |
|
21 | attr_protected :id | |
|
22 | end | |
|
23 | ||
|
21 | 24 | # model removed |
|
22 | 25 | class Permission < ActiveRecord::Base; end |
|
23 | 26 |
@@ -4,7 +4,7 class AddEnumerationsPosition < ActiveRecord::Migration | |||
|
4 | 4 | Enumeration.all.group_by(&:opt).each do |opt, enums| |
|
5 | 5 | enums.each_with_index do |enum, i| |
|
6 | 6 | # do not call model callbacks |
|
7 |
Enumeration. |
|
|
7 | Enumeration.where({:id => enum.id}).update_all("position = #{i+1}") | |
|
8 | 8 | end |
|
9 | 9 | end |
|
10 | 10 | end |
@@ -4,7 +4,7 class AddCustomFieldsPosition < ActiveRecord::Migration | |||
|
4 | 4 | CustomField.all.group_by(&:type).each do |t, fields| |
|
5 | 5 | fields.each_with_index do |field, i| |
|
6 | 6 | # do not call model callbacks |
|
7 |
CustomField. |
|
|
7 | CustomField.where({:id => field.id}).update_all("position = #{i+1}") | |
|
8 | 8 | end |
|
9 | 9 | end |
|
10 | 10 | end |
@@ -7,7 +7,7 class PopulateChangesetsUserId < ActiveRecord::Migration | |||
|
7 | 7 | username, email = $1.strip, $3 |
|
8 | 8 | u = User.find_by_login(username) |
|
9 | 9 | u ||= User.find_by_mail(email) unless email.blank? |
|
10 |
Changeset.update_all("user_id = #{u.id}" |
|
|
10 | Changeset.where(["committer = ?", committer]).update_all("user_id = #{u.id}") unless u.nil? | |
|
11 | 11 | end |
|
12 | 12 | end |
|
13 | 13 | end |
@@ -5,8 +5,8 class RemoveEnumerationsOpt < ActiveRecord::Migration | |||
|
5 | 5 | |
|
6 | 6 | def self.down |
|
7 | 7 | add_column :enumerations, :opt, :string, :limit => 4, :default => '', :null => false |
|
8 | Enumeration.update_all("opt = 'IPRI'", "type = 'IssuePriority'") | |
|
9 |
Enumeration.update_all("opt = 'DCAT'" |
|
|
10 |
Enumeration.update_all("opt = 'ACTI'" |
|
|
8 | Enumeration.where("type = 'IssuePriority'").update_all("opt = 'IPRI'") | |
|
9 | Enumeration.where("type = 'DocumentCategory'").update_all("opt = 'DCAT'") | |
|
10 | Enumeration.where("type = 'TimeEntryActivity'").update_all("opt = 'ACTI'") | |
|
11 | 11 | end |
|
12 | 12 | end |
@@ -1,6 +1,6 | |||
|
1 | 1 | class EnableCalendarAndGanttModulesWhereAppropriate < ActiveRecord::Migration |
|
2 | 2 | def self.up |
|
3 |
EnabledModule.where(:name => 'issue_tracking'). |
|
|
3 | EnabledModule.where(:name => 'issue_tracking').each do |e| | |
|
4 | 4 | EnabledModule.create(:name => 'calendar', :project_id => e.project_id) |
|
5 | 5 | EnabledModule.create(:name => 'gantt', :project_id => e.project_id) |
|
6 | 6 | end |
@@ -15,7 +15,8 class PopulateIssuesClosedOn < ActiveRecord::Migration | |||
|
15 | 15 | |
|
16 | 16 | # Then set closed_on for closed issues that weren't up updated by the above UPDATE |
|
17 | 17 | # No journal was found so we assume that they were closed on creation |
|
18 |
Issue. |
|
|
18 | Issue.where({:status_id => closed_status_ids, :closed_on => nil}). | |
|
19 | update_all("closed_on = created_on") | |
|
19 | 20 | end |
|
20 | 21 | end |
|
21 | 22 |
@@ -86,7 +86,7 http://www.redmine.org/ | |||
|
86 | 86 | * Defect #16655: start_date not set despite settings[default_issue_start_date_to_creation_date] being set. |
|
87 | 87 | * Defect #16668: Redmine links broken when object name contains special characters |
|
88 | 88 | * Defect #16669: Markdown formatter should use the :no_intra_emphasis extension |
|
89 |
* Defect #16708: Form is submitted when swit |
|
|
89 | * Defect #16708: Form is submitted when swithing tab | |
|
90 | 90 | * Defect #16739: custom_fields.json only returns single tracker instead of array of trackers |
|
91 | 91 | * Defect #16747: Remove useless settings when editing a query from the gantt |
|
92 | 92 | * Defect #16755: Field set as read-only still available in the issues list context menu |
@@ -7,7 +7,7 http://www.redmine.org/ | |||
|
7 | 7 | |
|
8 | 8 | == Requirements |
|
9 | 9 | |
|
10 | * Ruby 1.8.7, 1.9.2, 1.9.3, 2.0 or 2.1 | |
|
10 | * Ruby >= 1.9.3 | |
|
11 | 11 | * RubyGems |
|
12 | 12 | * Bundler >= 1.0.21 |
|
13 | 13 | |
@@ -30,9 +30,6 Optional: | |||
|
30 | 30 | 3. Configure the database parameters in config/database.yml |
|
31 | 31 | for the "production" environment (default database is MySQL and ruby1.9) |
|
32 | 32 | |
|
33 | If you're running Redmine with MySQL and ruby1.8, replace the adapter name | |
|
34 | with `mysql` | |
|
35 | ||
|
36 | 33 | 4. Install the required gems by running: |
|
37 | 34 | bundle install --without development test |
|
38 | 35 |
@@ -29,7 +29,7 module Redmine | |||
|
29 | 29 | send :include, Redmine::Acts::ActivityProvider::InstanceMethods |
|
30 | 30 | end |
|
31 | 31 | |
|
32 | options.assert_valid_keys(:type, :permission, :timestamp, :author_key, :find_options) | |
|
32 | options.assert_valid_keys(:type, :permission, :timestamp, :author_key, :find_options, :scope) | |
|
33 | 33 | self.activity_provider_options ||= {} |
|
34 | 34 | |
|
35 | 35 | # One model can provide different event types |
@@ -54,7 +54,7 module Redmine | |||
|
54 | 54 | provider_options = activity_provider_options[event_type] |
|
55 | 55 | raise "#{self.name} can not provide #{event_type} events." if provider_options.nil? |
|
56 | 56 | |
|
57 | scope = self | |
|
57 | scope = (provider_options[:scope] || self) | |
|
58 | 58 | |
|
59 | 59 | if from && to |
|
60 | 60 | scope = scope.where("#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to) |
@@ -79,7 +79,7 module Redmine | |||
|
79 | 79 | scope = scope.where(Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym, options)) |
|
80 | 80 | end |
|
81 | 81 | |
|
82 | scope.all(provider_options[:find_options].dup) | |
|
82 | scope.to_a | |
|
83 | 83 | end |
|
84 | 84 | end |
|
85 | 85 | end |
@@ -29,9 +29,8 module Redmine | |||
|
29 | 29 | attachable_options[:view_permission] = options.delete(:view_permission) || "view_#{self.name.pluralize.underscore}".to_sym |
|
30 | 30 | attachable_options[:delete_permission] = options.delete(:delete_permission) || "edit_#{self.name.pluralize.underscore}".to_sym |
|
31 | 31 | |
|
32 | has_many :attachments, options.merge(:as => :container, | |
|
33 | :order => "#{Attachment.table_name}.created_on ASC, #{Attachment.table_name}.id ASC", | |
|
34 | :dependent => :destroy) | |
|
32 | has_many :attachments, lambda {order("#{Attachment.table_name}.created_on ASC, #{Attachment.table_name}.id ASC")}, | |
|
33 | options.merge(:as => :container, :dependent => :destroy) | |
|
35 | 34 | send :include, Redmine::Acts::Attachable::InstanceMethods |
|
36 | 35 | before_save :attach_saved_attachments |
|
37 | 36 | end |
@@ -27,9 +27,8 module Redmine | |||
|
27 | 27 | return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods) |
|
28 | 28 | cattr_accessor :customizable_options |
|
29 | 29 | self.customizable_options = options |
|
30 | has_many :custom_values, :as => :customized, | |
|
31 |
: |
|
|
32 | :order => "#{CustomField.table_name}.position", | |
|
30 | has_many :custom_values, lambda {includes(:custom_field).order("#{CustomField.table_name}.position")}, | |
|
31 | :as => :customized, | |
|
33 | 32 | :dependent => :delete_all, |
|
34 | 33 | :validate => false |
|
35 | 34 | |
@@ -46,7 +45,7 module Redmine | |||
|
46 | 45 | end |
|
47 | 46 | |
|
48 | 47 | def available_custom_fields |
|
49 |
CustomField.where("type = '#{self.class.name}CustomField'").sorted.a |
|
|
48 | CustomField.where("type = '#{self.class.name}CustomField'").sorted.to_a | |
|
50 | 49 | end |
|
51 | 50 | |
|
52 | 51 | # Sets the values of the object's custom fields |
@@ -31,6 +31,7 module Redmine | |||
|
31 | 31 | # * :permission - permission required to search the model (default to :view_"objects") |
|
32 | 32 | def acts_as_searchable(options = {}) |
|
33 | 33 | return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods) |
|
34 | options.assert_valid_keys(:columns, :project_key, :date_column, :order_column, :search_custom_fields, :permission, :scope) | |
|
34 | 35 | |
|
35 | 36 | cattr_accessor :searchable_options |
|
36 | 37 | self.searchable_options = options |
@@ -70,7 +71,7 module Redmine | |||
|
70 | 71 | # TODO: make user an argument |
|
71 | 72 | user = User.current |
|
72 | 73 | tokens = [] << tokens unless tokens.is_a?(Array) |
|
73 |
projects = [] << projects |
|
|
74 | projects = [] << projects if projects.is_a?(Project) | |
|
74 | 75 | |
|
75 | 76 | limit_options = {} |
|
76 | 77 | limit_options[:limit] = options[:limit] if options[:limit] |
@@ -100,7 +101,10 module Redmine | |||
|
100 | 101 | |
|
101 | 102 | tokens_conditions = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort] |
|
102 | 103 | |
|
103 |
scope = self |
|
|
104 | scope = (searchable_options[:scope] || self) | |
|
105 | if scope.is_a? Proc | |
|
106 | scope = scope.call | |
|
107 | end | |
|
104 | 108 | project_conditions = [] |
|
105 | 109 | if searchable_options.has_key?(:permission) |
|
106 | 110 | project_conditions << Project.allowed_to_condition(user, searchable_options[:permission] || :view_project) |
@@ -118,10 +122,11 module Redmine | |||
|
118 | 122 | results_count = 0 |
|
119 | 123 | |
|
120 | 124 | scope = scope. |
|
121 |
in |
|
|
125 | joins(searchable_options[:include]). | |
|
122 | 126 | order("#{searchable_options[:order_column]} " + (options[:before] ? 'DESC' : 'ASC')). |
|
123 | 127 | where(project_conditions). |
|
124 | where(tokens_conditions) | |
|
128 | where(tokens_conditions). | |
|
129 | uniq | |
|
125 | 130 | |
|
126 | 131 | results_count = scope.count |
|
127 | 132 | |
@@ -129,7 +134,7 module Redmine | |||
|
129 | 134 | if options[:offset] |
|
130 | 135 | scope_with_limit = scope_with_limit.where("#{searchable_options[:date_column]} #{options[:before] ? '<' : '>'} ?", options[:offset]) |
|
131 | 136 | end |
|
132 |
results = scope_with_limit.a |
|
|
137 | results = scope_with_limit.to_a | |
|
133 | 138 | |
|
134 | 139 | [results, results_count] |
|
135 | 140 | end |
@@ -44,7 +44,7 module ActiveRecord | |||
|
44 | 44 | configuration.update(options) if options.is_a?(Hash) |
|
45 | 45 | |
|
46 | 46 | belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache] |
|
47 |
has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], |
|
|
47 | has_many :children, lambda {order(configuration[:order])}, :class_name => name, :foreign_key => configuration[:foreign_key], :dependent => configuration[:dependent] | |
|
48 | 48 | |
|
49 | 49 | scope :roots, lambda { |
|
50 | 50 | where("#{configuration[:foreign_key]} IS NULL"). |
@@ -68,7 +68,7 module Redmine | |||
|
68 | 68 | end |
|
69 | 69 | |
|
70 | 70 | def notified_watchers |
|
71 | notified = watcher_users.active | |
|
71 | notified = watcher_users.active.to_a | |
|
72 | 72 | notified.reject! {|user| user.mail.blank? || user.mail_notification == 'none'} |
|
73 | 73 | if respond_to?(:visible?) |
|
74 | 74 | notified.reject! {|user| !visible?(user)} |
@@ -63,12 +63,7 require 'redmine/themes' | |||
|
63 | 63 | require 'redmine/hook' |
|
64 | 64 | require 'redmine/plugin' |
|
65 | 65 | |
|
66 | if RUBY_VERSION < '1.9' | |
|
67 | require 'fastercsv' | |
|
68 | else | |
|
69 | require 'csv' | |
|
70 | FCSV = CSV | |
|
71 | end | |
|
66 | require 'csv' | |
|
72 | 67 | |
|
73 | 68 | Redmine::Scm::Base.add "Subversion" |
|
74 | 69 | Redmine::Scm::Base.add "Darcs" |
@@ -58,9 +58,11 module Redmine | |||
|
58 | 58 | if action.is_a?(Symbol) |
|
59 | 59 | perm = permission(action) |
|
60 | 60 | !perm.nil? && perm.read? |
|
61 | else | |
|
61 | elsif action.is_a?(Hash) | |
|
62 | 62 | s = "#{action[:controller]}/#{action[:action]}" |
|
63 | 63 | permissions.detect {|p| p.actions.include?(s) && p.read?}.present? |
|
64 | else | |
|
65 | raise ArgumentError.new("Symbol or a Hash expected, #{action.class.name} given: #{action}") | |
|
64 | 66 | end |
|
65 | 67 | end |
|
66 | 68 |
@@ -1,160 +1,71 | |||
|
1 | if RUBY_VERSION < '1.9' | |
|
2 | require 'iconv' | |
|
3 | end | |
|
4 | 1 | |
|
5 | 2 | module Redmine |
|
6 | 3 | module CodesetUtil |
|
7 | 4 | |
|
8 | 5 | def self.replace_invalid_utf8(str) |
|
9 | 6 | return str if str.nil? |
|
10 |
|
|
|
11 |
str. |
|
|
12 | if ! str.valid_encoding? | |
|
13 | str = str.encode("US-ASCII", :invalid => :replace, | |
|
14 | :undef => :replace, :replace => '?').encode("UTF-8") | |
|
15 | end | |
|
16 | elsif RUBY_PLATFORM == 'java' | |
|
17 | begin | |
|
18 | ic = Iconv.new('UTF-8', 'UTF-8') | |
|
19 | str = ic.iconv(str) | |
|
20 | rescue | |
|
21 | str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?') | |
|
22 | end | |
|
23 | else | |
|
24 | ic = Iconv.new('UTF-8', 'UTF-8') | |
|
25 | txtar = "" | |
|
26 | begin | |
|
27 | txtar += ic.iconv(str) | |
|
28 | rescue Iconv::IllegalSequence | |
|
29 | txtar += $!.success | |
|
30 | str = '?' + $!.failed[1,$!.failed.length] | |
|
31 | retry | |
|
32 | rescue | |
|
33 | txtar += $!.success | |
|
34 | end | |
|
35 | str = txtar | |
|
7 | str.force_encoding('UTF-8') | |
|
8 | if ! str.valid_encoding? | |
|
9 | str = str.encode("US-ASCII", :invalid => :replace, | |
|
10 | :undef => :replace, :replace => '?').encode("UTF-8") | |
|
36 | 11 | end |
|
37 | 12 | str |
|
38 | 13 | end |
|
39 | 14 | |
|
40 | 15 | def self.to_utf8(str, encoding) |
|
41 | 16 | return str if str.nil? |
|
42 |
str.force_encoding("ASCII-8BIT") |
|
|
17 | str.force_encoding("ASCII-8BIT") | |
|
43 | 18 | if str.empty? |
|
44 |
str.force_encoding("UTF-8") |
|
|
19 | str.force_encoding("UTF-8") | |
|
45 | 20 | return str |
|
46 | 21 | end |
|
47 | 22 | enc = encoding.blank? ? "UTF-8" : encoding |
|
48 | if str.respond_to?(:force_encoding) | |
|
49 | if enc.upcase != "UTF-8" | |
|
50 | str.force_encoding(enc) | |
|
51 | str = str.encode("UTF-8", :invalid => :replace, | |
|
52 | :undef => :replace, :replace => '?') | |
|
53 | else | |
|
54 | str.force_encoding("UTF-8") | |
|
55 | if ! str.valid_encoding? | |
|
56 | str = str.encode("US-ASCII", :invalid => :replace, | |
|
57 | :undef => :replace, :replace => '?').encode("UTF-8") | |
|
58 | end | |
|
59 | end | |
|
60 | elsif RUBY_PLATFORM == 'java' | |
|
61 | begin | |
|
62 | ic = Iconv.new('UTF-8', enc) | |
|
63 | str = ic.iconv(str) | |
|
64 | rescue | |
|
65 | str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?') | |
|
66 | end | |
|
23 | if enc.upcase != "UTF-8" | |
|
24 | str.force_encoding(enc) | |
|
25 | str = str.encode("UTF-8", :invalid => :replace, | |
|
26 | :undef => :replace, :replace => '?') | |
|
67 | 27 | else |
|
68 | ic = Iconv.new('UTF-8', enc) | |
|
69 | txtar = "" | |
|
70 | begin | |
|
71 | txtar += ic.iconv(str) | |
|
72 | rescue Iconv::IllegalSequence | |
|
73 | txtar += $!.success | |
|
74 | str = '?' + $!.failed[1,$!.failed.length] | |
|
75 | retry | |
|
76 | rescue | |
|
77 | txtar += $!.success | |
|
28 | str.force_encoding("UTF-8") | |
|
29 | if ! str.valid_encoding? | |
|
30 | str = str.encode("US-ASCII", :invalid => :replace, | |
|
31 | :undef => :replace, :replace => '?').encode("UTF-8") | |
|
78 | 32 | end |
|
79 | str = txtar | |
|
80 | 33 | end |
|
81 | 34 | str |
|
82 | 35 | end |
|
83 | 36 | |
|
84 | 37 | def self.to_utf8_by_setting(str) |
|
85 | 38 | return str if str.nil? |
|
86 |
|
|
|
87 | if str.respond_to?(:force_encoding) | |
|
88 | str.force_encoding('UTF-8') | |
|
89 | end | |
|
90 | str | |
|
39 | self.to_utf8_by_setting_internal(str).force_encoding('UTF-8') | |
|
91 | 40 | end |
|
92 | 41 | |
|
93 | 42 | def self.to_utf8_by_setting_internal(str) |
|
94 | 43 | return str if str.nil? |
|
95 |
|
|
|
96 | str.force_encoding('ASCII-8BIT') | |
|
97 | end | |
|
44 | str.force_encoding('ASCII-8BIT') | |
|
98 | 45 | return str if str.empty? |
|
99 | 46 | return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii |
|
100 |
|
|
|
101 | str.force_encoding('UTF-8') | |
|
102 | end | |
|
47 | str.force_encoding('UTF-8') | |
|
103 | 48 | encodings = Setting.repositories_encodings.split(',').collect(&:strip) |
|
104 | 49 | encodings.each do |encoding| |
|
105 | if str.respond_to?(:force_encoding) | |
|
106 | begin | |
|
107 |
str. |
|
|
108 | utf8 = str.encode('UTF-8') | |
|
109 | return utf8 if utf8.valid_encoding? | |
|
110 | rescue | |
|
111 | # do nothing here and try the next encoding | |
|
112 | end | |
|
113 | else | |
|
114 | begin | |
|
115 | return Iconv.conv('UTF-8', encoding, str) | |
|
116 | rescue Iconv::Failure | |
|
117 | # do nothing here and try the next encoding | |
|
118 | end | |
|
50 | begin | |
|
51 | str.force_encoding(encoding) | |
|
52 | utf8 = str.encode('UTF-8') | |
|
53 | return utf8 if utf8.valid_encoding? | |
|
54 | rescue | |
|
55 | # do nothing here and try the next encoding | |
|
119 | 56 | end |
|
120 | 57 | end |
|
121 |
|
|
|
122 | if str.respond_to?(:force_encoding) | |
|
123 | str.force_encoding('UTF-8') | |
|
124 | end | |
|
125 | str | |
|
58 | self.replace_invalid_utf8(str).force_encoding('UTF-8') | |
|
126 | 59 | end |
|
127 | 60 | |
|
128 | 61 | def self.from_utf8(str, encoding) |
|
129 | 62 | str ||= '' |
|
130 |
|
|
|
131 |
|
|
|
132 | if encoding.upcase != 'UTF-8' | |
|
133 | str = str.encode(encoding, :invalid => :replace, | |
|
134 | :undef => :replace, :replace => '?') | |
|
135 | else | |
|
136 | str = self.replace_invalid_utf8(str) | |
|
137 | end | |
|
138 | elsif RUBY_PLATFORM == 'java' | |
|
139 | begin | |
|
140 | ic = Iconv.new(encoding, 'UTF-8') | |
|
141 | str = ic.iconv(str) | |
|
142 | rescue | |
|
143 | str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?') | |
|
144 | end | |
|
63 | str.force_encoding('UTF-8') | |
|
64 | if encoding.upcase != 'UTF-8' | |
|
65 | str = str.encode(encoding, :invalid => :replace, | |
|
66 | :undef => :replace, :replace => '?') | |
|
145 | 67 | else |
|
146 | ic = Iconv.new(encoding, 'UTF-8') | |
|
147 | txtar = "" | |
|
148 | begin | |
|
149 | txtar += ic.iconv(str) | |
|
150 | rescue Iconv::IllegalSequence | |
|
151 | txtar += $!.success | |
|
152 | str = '?' + $!.failed[1, $!.failed.length] | |
|
153 | retry | |
|
154 | rescue | |
|
155 | txtar += $!.success | |
|
156 | end | |
|
157 | str = txtar | |
|
68 | str = self.replace_invalid_utf8(str) | |
|
158 | 69 | end |
|
159 | 70 | end |
|
160 | 71 | end |
@@ -15,35 +15,10 | |||
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | module ActiveRecord | |
|
19 | module FinderMethods | |
|
20 | def find_ids(*args) | |
|
21 | find_ids_with_associations | |
|
22 | end | |
|
23 | ||
|
24 | private | |
|
25 | ||
|
26 | def find_ids_with_associations | |
|
27 | join_dependency = construct_join_dependency_for_association_find | |
|
28 | relation = construct_relation_for_association_find_ids(join_dependency) | |
|
29 | rows = connection.select_all(relation, 'SQL', relation.bind_values) | |
|
30 | rows.map {|row| row["id"].to_i} | |
|
31 | rescue ThrowResult | |
|
32 | [] | |
|
33 | end | |
|
34 | ||
|
35 | def construct_relation_for_association_find_ids(join_dependency) | |
|
36 | relation = except(:includes, :eager_load, :preload, :select).select("#{table_name}.id") | |
|
37 | apply_join_dependency(relation, join_dependency) | |
|
38 | end | |
|
39 | end | |
|
40 | end | |
|
41 | ||
|
42 | 18 | class DateValidator < ActiveModel::EachValidator |
|
43 | 19 | def validate_each(record, attribute, value) |
|
44 | 20 | before_type_cast = record.attributes_before_type_cast[attribute.to_s] |
|
45 | 21 | if before_type_cast.is_a?(String) && before_type_cast.present? |
|
46 | # TODO: #*_date_before_type_cast returns a Mysql::Time with ruby1.8+mysql gem | |
|
47 | 22 | unless before_type_cast =~ /\A\d{4}-\d{2}-\d{2}( 00:00:00)?\z/ && value |
|
48 | 23 | record.errors.add attribute, :not_a_date |
|
49 | 24 | end |
@@ -36,13 +36,6 module Redmine #:nodoc: | |||
|
36 | 36 | s.gsub!(',', '.') |
|
37 | 37 | begin; Kernel.Float(s); rescue; nil; end |
|
38 | 38 | end |
|
39 | ||
|
40 | # Object#to_a removed in ruby1.9 | |
|
41 | if RUBY_VERSION > '1.9' | |
|
42 | def to_a | |
|
43 | [self.dup] | |
|
44 | end | |
|
45 | end | |
|
46 | 39 | end |
|
47 | 40 | end |
|
48 | 41 | end |
@@ -678,9 +678,7 module Redmine | |||
|
678 | 678 | def self.rdm_from_utf8(txt, encoding) |
|
679 | 679 | txt ||= '' |
|
680 | 680 | txt = Redmine::CodesetUtil.from_utf8(txt, encoding) |
|
681 |
|
|
|
682 | txt.force_encoding('ASCII-8BIT') | |
|
683 | end | |
|
681 | txt.force_encoding('ASCII-8BIT') | |
|
684 | 682 | txt |
|
685 | 683 | end |
|
686 | 684 |
@@ -597,18 +597,13 module Redmine | |||
|
597 | 597 | def target_class |
|
598 | 598 | @target_class ||= self.class.name[/^(.*::)?(.+)Format$/, 2].constantize rescue nil |
|
599 | 599 | end |
|
600 | ||
|
601 | def reset_target_class | |
|
602 | @target_class = nil | |
|
603 | end | |
|
604 | 600 | |
|
605 | 601 | def possible_custom_value_options(custom_value) |
|
606 | 602 | options = possible_values_options(custom_value.custom_field, custom_value.customized) |
|
607 | 603 | missing = [custom_value.value_was].flatten.reject(&:blank?) - options.map(&:last) |
|
608 | 604 | if missing.any? |
|
609 | 605 | options += target_class.where(:id => missing.map(&:to_i)).map {|o| [o.to_s, o.id.to_s]} |
|
610 | #TODO: use #sort_by! when ruby1.8 support is dropped | |
|
611 | options = options.sort_by(&:first) | |
|
606 | options.sort_by!(&:first) | |
|
612 | 607 | end |
|
613 | 608 | options |
|
614 | 609 | end |
@@ -167,7 +167,7 module Redmine | |||
|
167 | 167 | where("child.id IN (?)", ids). |
|
168 | 168 | order("#{Project.table_name}.lft ASC"). |
|
169 | 169 | uniq. |
|
170 |
a |
|
|
170 | to_a | |
|
171 | 171 | else |
|
172 | 172 | @projects = [] |
|
173 | 173 | end |
@@ -193,7 +193,7 module Redmine | |||
|
193 | 193 | # * Checking the url target (project only) |
|
194 | 194 | # * Checking the conditions of the item |
|
195 | 195 | def allowed_node?(node, user, project) |
|
196 | if project && user && !user.allowed_to?(node.url, project) | |
|
196 | if node.url.is_a?(Hash) && project && user && !user.allowed_to?(node.url, project) | |
|
197 | 197 | return false |
|
198 | 198 | end |
|
199 | 199 | if node.condition && !node.condition.call(project) |
@@ -18,17 +18,13 | |||
|
18 | 18 | require 'cgi' |
|
19 | 19 | require 'redmine/scm/adapters' |
|
20 | 20 | |
|
21 | if RUBY_VERSION < '1.9' | |
|
22 | require 'iconv' | |
|
23 | end | |
|
24 | ||
|
25 | 21 | module Redmine |
|
26 | 22 | module Scm |
|
27 | 23 | module Adapters |
|
28 | 24 | class AbstractAdapter #:nodoc: |
|
29 | 25 | |
|
30 | 26 | # raised if scm command exited with error, e.g. unknown revision. |
|
31 | class ScmCommandAborted < CommandFailed; end | |
|
27 | class ScmCommandAborted < ::Redmine::Scm::Adapters::CommandFailed; end | |
|
32 | 28 | |
|
33 | 29 | class << self |
|
34 | 30 | def client_command |
@@ -288,21 +284,12 module Redmine | |||
|
288 | 284 | def scm_iconv(to, from, str) |
|
289 | 285 | return nil if str.nil? |
|
290 | 286 | return str if to == from |
|
291 |
|
|
|
292 | str.force_encoding(from) | |
|
293 |
|
|
|
294 | str.encode(to) | |
|
295 | rescue Exception => err | |
|
296 | logger.error("failed to convert from #{from} to #{to}. #{err}") | |
|
297 | nil | |
|
298 | end | |
|
299 | else | |
|
300 | begin | |
|
301 | Iconv.conv(to, from, str) | |
|
302 | rescue Iconv::Failure => err | |
|
303 | logger.error("failed to convert from #{from} to #{to}. #{err}") | |
|
304 | nil | |
|
305 | end | |
|
287 | str.force_encoding(from) | |
|
288 | begin | |
|
289 | str.encode(to) | |
|
290 | rescue Exception => err | |
|
291 | logger.error("failed to convert from #{from} to #{to}. #{err}") | |
|
292 | nil | |
|
306 | 293 | end |
|
307 | 294 | end |
|
308 | 295 |
@@ -43,10 +43,7 module Redmine | |||
|
43 | 43 | end |
|
44 | 44 | |
|
45 | 45 | def scm_command_version |
|
46 | scm_version = scm_version_from_command_line.dup | |
|
47 | if scm_version.respond_to?(:force_encoding) | |
|
48 | scm_version.force_encoding('ASCII-8BIT') | |
|
49 | end | |
|
46 | scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT') | |
|
50 | 47 | if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) |
|
51 | 48 | m[2].scan(%r{\d+}).collect(&:to_i) |
|
52 | 49 | end |
@@ -100,7 +97,7 module Redmine | |||
|
100 | 97 | prefix_utf8 = "#{url}/#{path}".gsub('\\', '/') |
|
101 | 98 | logger.debug "PREFIX: #{prefix_utf8}" |
|
102 | 99 | prefix = scm_iconv(@path_encoding, 'UTF-8', prefix_utf8) |
|
103 |
prefix.force_encoding('ASCII-8BIT') |
|
|
100 | prefix.force_encoding('ASCII-8BIT') | |
|
104 | 101 | re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$} |
|
105 | 102 | io.each_line do |line| |
|
106 | 103 | next unless line =~ re |
@@ -43,10 +43,7 module Redmine | |||
|
43 | 43 | end |
|
44 | 44 | |
|
45 | 45 | def scm_command_version |
|
46 | scm_version = scm_version_from_command_line.dup | |
|
47 | if scm_version.respond_to?(:force_encoding) | |
|
48 | scm_version.force_encoding('ASCII-8BIT') | |
|
49 | end | |
|
46 | scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT') | |
|
50 | 47 | if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m) |
|
51 | 48 | m[2].scan(%r{\d+}).collect(&:to_i) |
|
52 | 49 | end |
@@ -94,7 +91,7 module Redmine | |||
|
94 | 91 | def entries(path=nil, identifier=nil, options={}) |
|
95 | 92 | logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'" |
|
96 | 93 | path_locale = scm_iconv(@path_encoding, 'UTF-8', path) |
|
97 |
path_locale.force_encoding("ASCII-8BIT") |
|
|
94 | path_locale.force_encoding("ASCII-8BIT") | |
|
98 | 95 | entries = Entries.new |
|
99 | 96 | cmd_args = %w|-q rls -e| |
|
100 | 97 | cmd_args << "-D" << time_to_cvstime_rlog(identifier) if identifier |
@@ -171,6 +168,7 module Redmine | |||
|
171 | 168 | file_state = nil |
|
172 | 169 | branch_map = nil |
|
173 | 170 | io.each_line() do |line| |
|
171 | line = line.strip | |
|
174 | 172 | if state != "revision" && /^#{ENDLOG}/ =~ line |
|
175 | 173 | commit_log = String.new |
|
176 | 174 | revision = nil |
@@ -43,10 +43,7 module Redmine | |||
|
43 | 43 | end |
|
44 | 44 | |
|
45 | 45 | def darcs_binary_version |
|
46 | darcsversion = darcs_binary_version_from_command_line.dup | |
|
47 | if darcsversion.respond_to?(:force_encoding) | |
|
48 | darcsversion.force_encoding('ASCII-8BIT') | |
|
49 | end | |
|
46 | darcsversion = darcs_binary_version_from_command_line.dup.force_encoding('ASCII-8BIT') | |
|
50 | 47 | if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)}) |
|
51 | 48 | m[2].scan(%r{\d+}).collect(&:to_i) |
|
52 | 49 | end |
@@ -47,10 +47,7 module Redmine | |||
|
47 | 47 | end |
|
48 | 48 | |
|
49 | 49 | def scm_command_version |
|
50 | scm_version = scm_version_from_command_line.dup | |
|
51 | if scm_version.respond_to?(:force_encoding) | |
|
52 | scm_version.force_encoding('ASCII-8BIT') | |
|
53 | end | |
|
50 | scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT') | |
|
54 | 51 | if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) |
|
55 | 52 | m[2].scan(%r{\d+}).collect(&:to_i) |
|
56 | 53 | end |
@@ -145,10 +142,7 module Redmine | |||
|
145 | 142 | type = $1 |
|
146 | 143 | sha = $2 |
|
147 | 144 | size = $3 |
|
148 | name = $4 | |
|
149 | if name.respond_to?(:force_encoding) | |
|
150 | name.force_encoding(@path_encoding) | |
|
151 | end | |
|
145 | name = $4.force_encoding(@path_encoding) | |
|
152 | 146 | full_path = p.empty? ? name : "#{p}/#{name}" |
|
153 | 147 | n = scm_iconv('UTF-8', @path_encoding, name) |
|
154 | 148 | full_p = scm_iconv('UTF-8', @path_encoding, full_path) |
@@ -54,10 +54,7 module Redmine | |||
|
54 | 54 | # The hg version is expressed either as a |
|
55 | 55 | # release number (eg 0.9.5 or 1.0) or as a revision |
|
56 | 56 | # id composed of 12 hexa characters. |
|
57 | theversion = hgversion_from_command_line.dup | |
|
58 | if theversion.respond_to?(:force_encoding) | |
|
59 | theversion.force_encoding('ASCII-8BIT') | |
|
60 | end | |
|
57 | theversion = hgversion_from_command_line.dup.force_encoding('ASCII-8BIT') | |
|
61 | 58 | if m = theversion.match(%r{\A(.*?)((\d+\.)+\d+)}) |
|
62 | 59 | m[2].scan(%r{\d+}).collect(&:to_i) |
|
63 | 60 | end |
@@ -130,10 +127,7 module Redmine | |||
|
130 | 127 | def summary |
|
131 | 128 | return @summary if @summary |
|
132 | 129 | hg 'rhsummary' do |io| |
|
133 | output = io.read | |
|
134 | if output.respond_to?(:force_encoding) | |
|
135 | output.force_encoding('UTF-8') | |
|
136 | end | |
|
130 | output = io.read.force_encoding('UTF-8') | |
|
137 | 131 | begin |
|
138 | 132 | @summary = parse_xml(output)['rhsummary'] |
|
139 | 133 | rescue |
@@ -146,10 +140,7 module Redmine | |||
|
146 | 140 | p1 = scm_iconv(@path_encoding, 'UTF-8', path) |
|
147 | 141 | manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)), |
|
148 | 142 | CGI.escape(without_leading_slash(p1.to_s))) do |io| |
|
149 | output = io.read | |
|
150 | if output.respond_to?(:force_encoding) | |
|
151 | output.force_encoding('UTF-8') | |
|
152 | end | |
|
143 | output = io.read.force_encoding('UTF-8') | |
|
153 | 144 | begin |
|
154 | 145 | parse_xml(output)['rhmanifest']['repository']['manifest'] |
|
155 | 146 | rescue |
@@ -193,10 +184,7 module Redmine | |||
|
193 | 184 | hg_args << '--limit' << options[:limit] if options[:limit] |
|
194 | 185 | hg_args << hgtarget(path) unless path.blank? |
|
195 | 186 | log = hg(*hg_args) do |io| |
|
196 | output = io.read | |
|
197 | if output.respond_to?(:force_encoding) | |
|
198 | output.force_encoding('UTF-8') | |
|
199 | end | |
|
187 | output = io.read.force_encoding('UTF-8') | |
|
200 | 188 | begin |
|
201 | 189 | # Mercurial < 1.5 does not support footer template for '</log>' |
|
202 | 190 | parse_xml("#{output}</log>")['log'] |
@@ -278,7 +266,7 module Redmine | |||
|
278 | 266 | blame = Annotate.new |
|
279 | 267 | hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io| |
|
280 | 268 | io.each_line do |line| |
|
281 |
line.force_encoding('ASCII-8BIT') |
|
|
269 | line.force_encoding('ASCII-8BIT') | |
|
282 | 270 | next unless line =~ %r{^([^:]+)\s(\d+)\s([0-9a-f]+):\s(.*)$} |
|
283 | 271 | r = Revision.new(:author => $1.strip, :revision => $2, :scmid => $3, |
|
284 | 272 | :identifier => $3) |
@@ -46,10 +46,7 module Redmine | |||
|
46 | 46 | end |
|
47 | 47 | |
|
48 | 48 | def svn_binary_version |
|
49 | scm_version = scm_version_from_command_line.dup | |
|
50 | if scm_version.respond_to?(:force_encoding) | |
|
51 | scm_version.force_encoding('ASCII-8BIT') | |
|
52 | end | |
|
49 | scm_version = scm_version_from_command_line.dup.force_encoding('ASCII-8BIT') | |
|
53 | 50 | if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}) |
|
54 | 51 | m[2].scan(%r{\d+}).collect(&:to_i) |
|
55 | 52 | end |
@@ -66,10 +63,7 module Redmine | |||
|
66 | 63 | cmd << credentials_string |
|
67 | 64 | info = nil |
|
68 | 65 | shellout(cmd) do |io| |
|
69 | output = io.read | |
|
70 | if output.respond_to?(:force_encoding) | |
|
71 | output.force_encoding('UTF-8') | |
|
72 | end | |
|
66 | output = io.read.force_encoding('UTF-8') | |
|
73 | 67 | begin |
|
74 | 68 | doc = parse_xml(output) |
|
75 | 69 | # root_url = doc.elements["info/entry/repository/root"].text |
@@ -98,10 +92,7 module Redmine | |||
|
98 | 92 | cmd = "#{self.class.sq_bin} list --xml #{target(path)}@#{identifier}" |
|
99 | 93 | cmd << credentials_string |
|
100 | 94 | shellout(cmd) do |io| |
|
101 | output = io.read | |
|
102 | if output.respond_to?(:force_encoding) | |
|
103 | output.force_encoding('UTF-8') | |
|
104 | end | |
|
95 | output = io.read.force_encoding('UTF-8') | |
|
105 | 96 | begin |
|
106 | 97 | doc = parse_xml(output) |
|
107 | 98 | each_xml_element(doc['lists']['list'], 'entry') do |entry| |
@@ -141,10 +132,7 module Redmine | |||
|
141 | 132 | cmd << credentials_string |
|
142 | 133 | properties = {} |
|
143 | 134 | shellout(cmd) do |io| |
|
144 | output = io.read | |
|
145 | if output.respond_to?(:force_encoding) | |
|
146 | output.force_encoding('UTF-8') | |
|
147 | end | |
|
135 | output = io.read.force_encoding('UTF-8') | |
|
148 | 136 | begin |
|
149 | 137 | doc = parse_xml(output) |
|
150 | 138 | each_xml_element(doc['properties']['target'], 'property') do |property| |
@@ -168,10 +156,7 module Redmine | |||
|
168 | 156 | cmd << " --limit #{options[:limit].to_i}" if options[:limit] |
|
169 | 157 | cmd << ' ' + target(path) |
|
170 | 158 | shellout(cmd) do |io| |
|
171 | output = io.read | |
|
172 | if output.respond_to?(:force_encoding) | |
|
173 | output.force_encoding('UTF-8') | |
|
174 | end | |
|
159 | output = io.read.force_encoding('UTF-8') | |
|
175 | 160 | begin |
|
176 | 161 | doc = parse_xml(output) |
|
177 | 162 | each_xml_element(doc['log'], 'logentry') do |logentry| |
@@ -199,28 +199,10 module Redmine | |||
|
199 | 199 | while starting < max && line_left[starting] == line_right[starting] |
|
200 | 200 | starting += 1 |
|
201 | 201 | end |
|
202 | if (! "".respond_to?(:force_encoding)) && starting < line_left.size | |
|
203 | while line_left[starting].ord.between?(128, 191) && starting > 0 | |
|
204 | starting -= 1 | |
|
205 | end | |
|
206 | end | |
|
207 | 202 | ending = -1 |
|
208 | 203 | while ending >= -(max - starting) && (line_left[ending] == line_right[ending]) |
|
209 | 204 | ending -= 1 |
|
210 | 205 | end |
|
211 | if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size) | |
|
212 | while line_left[ending].ord.between?(128, 255) && ending < -1 | |
|
213 | if line_left[ending].ord.between?(128, 191) | |
|
214 | if line_left[ending + 1].ord.between?(128, 191) | |
|
215 | ending += 1 | |
|
216 | else | |
|
217 | break | |
|
218 | end | |
|
219 | else | |
|
220 | ending += 1 | |
|
221 | end | |
|
222 | end | |
|
223 | end | |
|
224 | 206 | unless starting == 0 && ending == -1 |
|
225 | 207 | [starting, ending] |
|
226 | 208 | end |
@@ -279,7 +261,7 module Redmine | |||
|
279 | 261 | |
|
280 | 262 | def line_to_html(line, offsets) |
|
281 | 263 | html = line_to_html_raw(line, offsets) |
|
282 |
html.force_encoding('UTF-8') |
|
|
264 | html.force_encoding('UTF-8') | |
|
283 | 265 | html |
|
284 | 266 | end |
|
285 | 267 |
@@ -33,7 +33,7 namespace :ci do | |||
|
33 | 33 | else |
|
34 | 34 | Rake::Task["test"].invoke |
|
35 | 35 | end |
|
36 |
# Rake::Task["test:ui"].invoke |
|
|
36 | # Rake::Task["test:ui"].invoke | |
|
37 | 37 | end |
|
38 | 38 | |
|
39 | 39 | desc "Finish the build" |
@@ -52,7 +52,7 file 'config/database.yml' do | |||
|
52 | 52 | |
|
53 | 53 | case database |
|
54 | 54 | when 'mysql' |
|
55 |
dev_conf = {'adapter' => |
|
|
55 | dev_conf = {'adapter' => 'mysql2', | |
|
56 | 56 | 'database' => dev_db_name, 'host' => 'localhost', |
|
57 | 57 | 'encoding' => 'utf8'} |
|
58 | 58 | if ENV['RUN_ON_NOT_OFFICIAL'] |
@@ -68,9 +68,6 namespace :locales do | |||
|
68 | 68 | desc <<-END_DESC |
|
69 | 69 | Removes a translation string from all locale file (only works for top-level childless non-multiline keys, probably doesn\'t work on windows). |
|
70 | 70 | |
|
71 | This task does not work on Ruby 1.8.6. | |
|
72 | You need to use Ruby 1.8.7 or later. | |
|
73 | ||
|
74 | 71 | Options: |
|
75 | 72 | key=key_1,key_2 Comma-separated list of keys to delete |
|
76 | 73 | skip=en,de Comma-separated list of locale files to ignore (filename without extension) |
@@ -18,7 +18,6 | |||
|
18 | 18 | desc 'Mantis migration script' |
|
19 | 19 | |
|
20 | 20 | require 'active_record' |
|
21 | require 'iconv' if RUBY_VERSION < '1.9' | |
|
22 | 21 | require 'pp' |
|
23 | 22 | |
|
24 | 23 | namespace :redmine do |
@@ -452,12 +451,7 task :migrate_from_mantis => :environment do | |||
|
452 | 451 | end |
|
453 | 452 | |
|
454 | 453 | def self.encode(text) |
|
455 | if RUBY_VERSION < '1.9' | |
|
456 | @ic ||= Iconv.new('UTF-8', @charset) | |
|
457 | @ic.iconv text | |
|
458 | else | |
|
459 | text.to_s.force_encoding(@charset).encode('UTF-8') | |
|
460 | end | |
|
454 | text.to_s.force_encoding(@charset).encode('UTF-8') | |
|
461 | 455 | end |
|
462 | 456 | end |
|
463 | 457 |
@@ -16,7 +16,6 | |||
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | require 'active_record' |
|
19 | require 'iconv' if RUBY_VERSION < '1.9' | |
|
20 | 19 | require 'pp' |
|
21 | 20 | |
|
22 | 21 | namespace :redmine do |
@@ -155,7 +154,7 namespace :redmine do | |||
|
155 | 154 | attachment_type = read_attribute(:type) |
|
156 | 155 | #replace exotic characters with their hex representation to avoid invalid filenames |
|
157 | 156 | trac_file = filename.gsub( /[^a-zA-Z0-9\-_\.!~*']/n ) do |x| |
|
158 |
codepoint = |
|
|
157 | codepoint = x.codepoints.to_a[0] | |
|
159 | 158 | sprintf('%%%02x', codepoint) |
|
160 | 159 | end |
|
161 | 160 | "#{TracMigrate.trac_attachments_directory}/#{attachment_type}/#{id}/#{trac_file}" |
@@ -715,12 +714,7 namespace :redmine do | |||
|
715 | 714 | end |
|
716 | 715 | |
|
717 | 716 | def self.encode(text) |
|
718 | if RUBY_VERSION < '1.9' | |
|
719 | @ic ||= Iconv.new('UTF-8', @charset) | |
|
720 | @ic.iconv text | |
|
721 | else | |
|
722 | text.to_s.force_encoding(@charset).encode('UTF-8') | |
|
723 | end | |
|
717 | text.to_s.force_encoding(@charset).encode('UTF-8') | |
|
724 | 718 | end |
|
725 | 719 | end |
|
726 | 720 |
@@ -1,6 +1,2 | |||
|
1 | 1 | #!/usr/bin/env ruby |
|
2 | ||
|
3 | ENV["RAILS_ENV"] ||= "production" | |
|
4 | require File.expand_path(File.dirname(__FILE__) + "/../config/environment") | |
|
5 | puts | |
|
6 | puts Redmine::Info.environment | |
|
2 | abort "script/about no longer exists, please use bin/about instead." |
@@ -1,6 +1,2 | |||
|
1 | 1 | #!/usr/bin/env ruby |
|
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. | |
|
3 | ||
|
4 | APP_PATH = File.expand_path('../../config/application', __FILE__) | |
|
5 | require File.expand_path('../../config/boot', __FILE__) | |
|
6 | require 'rails/commands' | |
|
2 | abort "script/rails no longer exists, please use bin/rails instead." |
@@ -72,8 +72,8 class AccountControllerTest < ActionController::TestCase | |||
|
72 | 72 | end |
|
73 | 73 | |
|
74 | 74 | def test_login_with_suburi_should_redirect_to_back_url_param |
|
75 |
@relative_url_root = |
|
|
76 |
|
|
|
75 | @relative_url_root = Redmine::Utils.relative_url_root | |
|
76 | Redmine::Utils.relative_url_root = '/redmine' | |
|
77 | 77 | |
|
78 | 78 | back_urls = [ |
|
79 | 79 | 'http://test.host/redmine/issues/show/1', |
@@ -84,7 +84,7 class AccountControllerTest < ActionController::TestCase | |||
|
84 | 84 | assert_redirected_to back_url |
|
85 | 85 | end |
|
86 | 86 | ensure |
|
87 |
|
|
|
87 | Redmine::Utils.relative_url_root = @relative_url_root | |
|
88 | 88 | end |
|
89 | 89 | |
|
90 | 90 | def test_login_should_not_redirect_to_another_host |
@@ -99,8 +99,8 class AccountControllerTest < ActionController::TestCase | |||
|
99 | 99 | end |
|
100 | 100 | |
|
101 | 101 | def test_login_with_suburi_should_not_redirect_to_another_suburi |
|
102 |
@relative_url_root = |
|
|
103 |
|
|
|
102 | @relative_url_root = Redmine::Utils.relative_url_root | |
|
103 | Redmine::Utils.relative_url_root = '/redmine' | |
|
104 | 104 | |
|
105 | 105 | back_urls = [ |
|
106 | 106 | 'http://test.host/', |
@@ -115,7 +115,7 class AccountControllerTest < ActionController::TestCase | |||
|
115 | 115 | assert_redirected_to '/my/page' |
|
116 | 116 | end |
|
117 | 117 | ensure |
|
118 |
|
|
|
118 | Redmine::Utils.relative_url_root = @relative_url_root | |
|
119 | 119 | end |
|
120 | 120 | |
|
121 | 121 | def test_login_with_wrong_password |
@@ -127,11 +127,13 class ActivitiesControllerTest < ActionController::TestCase | |||
|
127 | 127 | end |
|
128 | 128 | |
|
129 | 129 | def test_index_atom_feed_with_one_item_type |
|
130 | get :index, :format => 'atom', :show_issues => '1' | |
|
131 | assert_response :success | |
|
132 | assert_template 'common/feed' | |
|
133 | ||
|
134 | assert_select 'title', :text => /Issues/ | |
|
130 | with_settings :default_language => 'en' do | |
|
131 | get :index, :format => 'atom', :show_issues => '1' | |
|
132 | assert_response :success | |
|
133 | assert_template 'common/feed' | |
|
134 | ||
|
135 | assert_select 'title', :text => /Issues/ | |
|
136 | end | |
|
135 | 137 | end |
|
136 | 138 | |
|
137 | 139 | def test_index_should_show_private_notes_with_permission_only |
@@ -139,8 +139,7 class AttachmentsControllerTest < ActionController::TestCase | |||
|
139 | 139 | assert a.save |
|
140 | 140 | assert_equal 'japanese-utf-8.txt', a.filename |
|
141 | 141 | |
|
142 | str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" | |
|
143 | str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding) | |
|
142 | str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8') | |
|
144 | 143 | |
|
145 | 144 | get :show, :id => a.id |
|
146 | 145 | assert_response :success |
@@ -48,10 +48,10 class CalendarsControllerTest < ActionController::TestCase | |||
|
48 | 48 | end |
|
49 | 49 | |
|
50 | 50 | def test_week_number_calculation |
|
51 |
|
|
|
52 | ||
|
53 | get :show, :month => '1', :year => '2010' | |
|
54 | assert_response :success | |
|
51 | with_settings :start_of_week => 7 do | |
|
52 | get :show, :month => '1', :year => '2010' | |
|
53 | assert_response :success | |
|
54 | end | |
|
55 | 55 | |
|
56 | 56 | assert_select 'tr' do |
|
57 | 57 | assert_select 'td.week-number', :text => '53' |
@@ -65,9 +65,10 class CalendarsControllerTest < ActionController::TestCase | |||
|
65 | 65 | assert_select 'td.even', :text => '9' |
|
66 | 66 | end |
|
67 | 67 | |
|
68 |
|
|
|
69 | get :show, :month => '1', :year => '2010' | |
|
70 | assert_response :success | |
|
68 | with_settings :start_of_week => 1 do | |
|
69 | get :show, :month => '1', :year => '2010' | |
|
70 | assert_response :success | |
|
71 | end | |
|
71 | 72 | |
|
72 | 73 | assert_select 'tr' do |
|
73 | 74 | assert_select 'td.week-number', :text => '53' |
@@ -56,12 +56,14 class ContextMenusControllerTest < ActionController::TestCase | |||
|
56 | 56 | end |
|
57 | 57 | |
|
58 | 58 | def test_context_menu_one_issue_by_anonymous |
|
59 | get :issues, :ids => [1] | |
|
60 | assert_response :success | |
|
61 | assert_template 'context_menus/issues' | |
|
62 | assert_tag :tag => 'a', :content => 'Delete', | |
|
63 | :attributes => { :href => '#', | |
|
64 | :class => 'icon-del disabled' } | |
|
59 | with_settings :default_language => 'en' do | |
|
60 | get :issues, :ids => [1] | |
|
61 | assert_response :success | |
|
62 | assert_template 'context_menus/issues' | |
|
63 | assert_tag :tag => 'a', :content => 'Delete', | |
|
64 | :attributes => { :href => '#', | |
|
65 | :class => 'icon-del disabled' } | |
|
66 | end | |
|
65 | 67 | end |
|
66 | 68 | |
|
67 | 69 | def test_context_menu_multiple_issues_of_same_project |
@@ -112,7 +112,7 class CustomFieldsControllerTest < ActionController::TestCase | |||
|
112 | 112 | end |
|
113 | 113 | |
|
114 | 114 | def test_new_js |
|
115 | get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}, :format => 'js' | |
|
115 | xhr :get, :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}, :format => 'js' | |
|
116 | 116 | assert_response :success |
|
117 | 117 | assert_template 'new' |
|
118 | 118 | assert_equal 'text/javascript', response.content_type |
@@ -201,7 +201,7 class GroupsControllerTest < ActionController::TestCase | |||
|
201 | 201 | end |
|
202 | 202 | |
|
203 | 203 | def test_autocomplete_for_user |
|
204 | get :autocomplete_for_user, :id => 10, :q => 'smi', :format => 'js' | |
|
204 | xhr :get, :autocomplete_for_user, :id => 10, :q => 'smi', :format => 'js' | |
|
205 | 205 | assert_response :success |
|
206 | 206 | assert_include 'John Smith', response.body |
|
207 | 207 | end |
@@ -474,12 +474,8 class IssuesControllerTest < ActionController::TestCase | |||
|
474 | 474 | |
|
475 | 475 | def test_index_csv_big_5 |
|
476 | 476 | with_settings :default_language => "zh-TW" do |
|
477 | str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88" | |
|
478 | str_big5 = "\xa4@\xa4\xeb" | |
|
479 | if str_utf8.respond_to?(:force_encoding) | |
|
480 | str_utf8.force_encoding('UTF-8') | |
|
481 | str_big5.force_encoding('Big5') | |
|
482 | end | |
|
477 | str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88".force_encoding('UTF-8') | |
|
478 | str_big5 = "\xa4@\xa4\xeb".force_encoding('Big5') | |
|
483 | 479 | issue = Issue.generate!(:subject => str_utf8) |
|
484 | 480 | |
|
485 | 481 | get :index, :project_id => 1, |
@@ -488,10 +484,7 class IssuesControllerTest < ActionController::TestCase | |||
|
488 | 484 | :format => 'csv' |
|
489 | 485 | assert_equal 'text/csv; header=present', @response.content_type |
|
490 | 486 | lines = @response.body.chomp.split("\n") |
|
491 | s1 = "\xaa\xac\xbaA" | |
|
492 | if str_utf8.respond_to?(:force_encoding) | |
|
493 | s1.force_encoding('Big5') | |
|
494 | end | |
|
487 | s1 = "\xaa\xac\xbaA".force_encoding('Big5') | |
|
495 | 488 | assert_include s1, lines[0] |
|
496 | 489 | assert_include str_big5, lines[1] |
|
497 | 490 | end |
@@ -499,10 +492,7 class IssuesControllerTest < ActionController::TestCase | |||
|
499 | 492 | |
|
500 | 493 | def test_index_csv_cannot_convert_should_be_replaced_big_5 |
|
501 | 494 | with_settings :default_language => "zh-TW" do |
|
502 | str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85" | |
|
503 | if str_utf8.respond_to?(:force_encoding) | |
|
504 | str_utf8.force_encoding('UTF-8') | |
|
505 | end | |
|
495 | str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8') | |
|
506 | 496 | issue = Issue.generate!(:subject => str_utf8) |
|
507 | 497 | |
|
508 | 498 | get :index, :project_id => 1, |
@@ -513,21 +503,11 class IssuesControllerTest < ActionController::TestCase | |||
|
513 | 503 | :set_filter => 1 |
|
514 | 504 | assert_equal 'text/csv; header=present', @response.content_type |
|
515 | 505 | lines = @response.body.chomp.split("\n") |
|
516 | s1 = "\xaa\xac\xbaA" # status | |
|
517 | if str_utf8.respond_to?(:force_encoding) | |
|
518 | s1.force_encoding('Big5') | |
|
519 | end | |
|
506 | s1 = "\xaa\xac\xbaA".force_encoding('Big5') # status | |
|
520 | 507 | assert lines[0].include?(s1) |
|
521 | 508 | s2 = lines[1].split(",")[2] |
|
522 | if s1.respond_to?(:force_encoding) | |
|
523 | s3 = "\xa5H?" # subject | |
|
524 | s3.force_encoding('Big5') | |
|
525 | assert_equal s3, s2 | |
|
526 | elsif RUBY_PLATFORM == 'java' | |
|
527 | assert_equal "??", s2 | |
|
528 | else | |
|
529 | assert_equal "\xa5H???", s2 | |
|
530 | end | |
|
509 | s3 = "\xa5H?".force_encoding('Big5') # subject | |
|
510 | assert_equal s3, s2 | |
|
531 | 511 | end |
|
532 | 512 | end |
|
533 | 513 | |
@@ -3120,20 +3100,15 class IssuesControllerTest < ActionController::TestCase | |||
|
3120 | 3100 | def test_put_update_with_attachment_that_fails_to_save |
|
3121 | 3101 | set_tmp_attachments_directory |
|
3122 | 3102 | |
|
3123 | # Delete all fixtured journals, a race condition can occur causing the wrong | |
|
3124 | # journal to get fetched in the next find. | |
|
3125 | Journal.delete_all | |
|
3126 | ||
|
3127 | # Mock out the unsaved attachment | |
|
3128 | Attachment.any_instance.stubs(:create).returns(Attachment.new) | |
|
3129 | ||
|
3130 | 3103 | # anonymous user |
|
3131 | put :update, | |
|
3132 | :id => 1, | |
|
3133 | :issue => {:notes => ''}, | |
|
3134 | :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} | |
|
3135 | assert_redirected_to :action => 'show', :id => '1' | |
|
3136 | assert_equal '1 file(s) could not be saved.', flash[:warning] | |
|
3104 | with_settings :attachment_max_size => 0 do | |
|
3105 | put :update, | |
|
3106 | :id => 1, | |
|
3107 | :issue => {:notes => ''}, | |
|
3108 | :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}} | |
|
3109 | assert_redirected_to :action => 'show', :id => '1' | |
|
3110 | assert_equal '1 file(s) could not be saved.', flash[:warning] | |
|
3111 | end | |
|
3137 | 3112 | end |
|
3138 | 3113 | |
|
3139 | 3114 | def test_put_update_with_no_change |
@@ -3379,7 +3354,7 class IssuesControllerTest < ActionController::TestCase | |||
|
3379 | 3354 | post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1} |
|
3380 | 3355 | assert_response :success |
|
3381 | 3356 | assert_template 'bulk_edit' |
|
3382 |
assert_equal Project.find(1).shared_versions.open.a |
|
|
3357 | assert_equal Project.find(1).shared_versions.open.to_a.sort, assigns(:versions).sort | |
|
3383 | 3358 | |
|
3384 | 3359 | assert_select 'select[name=?]', 'issue[fixed_version_id]' do |
|
3385 | 3360 | assert_select 'option', :text => '2.0' |
@@ -199,8 +199,8 class IssuesCustomFieldsVisibilityTest < ActionController::TestCase | |||
|
199 | 199 | p1 = Project.generate! |
|
200 | 200 | p2 = Project.generate! |
|
201 | 201 | user = User.generate! |
|
202 |
User.add_to_project(user, p1, Role.where(:id => [1, 3]).a |
|
|
203 |
User.add_to_project(user, p2, Role.where(:id => 3).a |
|
|
202 | User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a) | |
|
203 | User.add_to_project(user, p2, Role.where(:id => 3).to_a) | |
|
204 | 204 | Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'}) |
|
205 | 205 | Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'}) |
|
206 | 206 | Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'}) |
@@ -104,7 +104,7 class MembersControllerTest < ActionController::TestCase | |||
|
104 | 104 | end |
|
105 | 105 | |
|
106 | 106 | def test_autocomplete |
|
107 | get :autocomplete, :project_id => 1, :q => 'mis', :format => 'js' | |
|
107 | xhr :get, :autocomplete, :project_id => 1, :q => 'mis', :format => 'js' | |
|
108 | 108 | assert_response :success |
|
109 | 109 | assert_include 'User Misc', response.body |
|
110 | 110 | end |
@@ -59,8 +59,8 class MessagesControllerTest < ActionController::TestCase | |||
|
59 | 59 | assert_template 'show' |
|
60 | 60 | replies = assigns(:replies) |
|
61 | 61 | assert_not_nil replies |
|
62 |
assert |
|
|
63 |
assert |
|
|
62 | assert_not_include message.children.reorder('id').first, replies | |
|
63 | assert_include message.children.reorder('id').last, replies | |
|
64 | 64 | end |
|
65 | 65 | |
|
66 | 66 | def test_show_with_reply_permission |
@@ -167,7 +167,7 class MyControllerTest < ActionController::TestCase | |||
|
167 | 167 | :new_password_confirmation => 'secret1234' |
|
168 | 168 | assert_response :success |
|
169 | 169 | assert_template 'password' |
|
170 |
assert_error_tag :content => /Password doesn |
|
|
170 | assert_error_tag :content => /Password doesn.*t match confirmation/ | |
|
171 | 171 | |
|
172 | 172 | # wrong password |
|
173 | 173 | post :password, :password => 'wrongpassword', |
@@ -26,7 +26,7 class RepositoriesBazaarControllerTest < ActionController::TestCase | |||
|
26 | 26 | REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s |
|
27 | 27 | REPOSITORY_PATH_TRUNK = File.join(REPOSITORY_PATH, "trunk") |
|
28 | 28 | PRJ_ID = 3 |
|
29 | CHAR_1_UTF8_HEX = "\xc3\x9c" | |
|
29 | CHAR_1_UTF8_HEX = "\xc3\x9c".dup.force_encoding('UTF-8') | |
|
30 | 30 | |
|
31 | 31 | def setup |
|
32 | 32 | User.current = nil |
@@ -36,10 +36,6 class RepositoriesBazaarControllerTest < ActionController::TestCase | |||
|
36 | 36 | :url => REPOSITORY_PATH_TRUNK, |
|
37 | 37 | :log_encoding => 'UTF-8') |
|
38 | 38 | assert @repository |
|
39 | @char_1_utf8 = CHAR_1_UTF8_HEX.dup | |
|
40 | if @char_1_utf8.respond_to?(:force_encoding) | |
|
41 | @char_1_utf8.force_encoding('UTF-8') | |
|
42 | end | |
|
43 | 39 | end |
|
44 | 40 | |
|
45 | 41 | if File.directory?(REPOSITORY_PATH) |
@@ -176,31 +172,29 class RepositoriesBazaarControllerTest < ActionController::TestCase | |||
|
176 | 172 | end |
|
177 | 173 | end |
|
178 | 174 | |
|
179 | if REPOSITORY_PATH.respond_to?(:force_encoding) | |
|
180 | def test_annotate_author_non_ascii | |
|
181 | log_encoding = nil | |
|
182 |
|
|
|
183 |
|
|
|
184 | log_encoding = Encoding.locale_charmap | |
|
185 | end | |
|
186 | unless log_encoding.nil? | |
|
187 | repository = Repository::Bazaar.create( | |
|
188 | :project => @project, | |
|
189 |
|
|
|
190 |
|
|
|
191 | :log_encoding => log_encoding) | |
|
192 | assert repository | |
|
193 | get :annotate, :id => PRJ_ID, :repository_id => 'author_non_ascii', | |
|
194 | :path => repository_path_hash(['author-non-ascii-test.txt'])[:param] | |
|
195 | assert_response :success | |
|
196 | assert_template 'annotate' | |
|
197 |
assert_select " |
|
|
198 |
assert_select " |
|
|
199 |
|
|
|
200 |
assert_select "+ td |
|
|
201 | assert_select "+ td", | |
|
202 | :text => "author non ASCII test" | |
|
203 | end | |
|
175 | def test_annotate_author_non_ascii | |
|
176 | log_encoding = nil | |
|
177 | if Encoding.locale_charmap == "UTF-8" || | |
|
178 | Encoding.locale_charmap == "ISO-8859-1" | |
|
179 | log_encoding = Encoding.locale_charmap | |
|
180 | end | |
|
181 | unless log_encoding.nil? | |
|
182 | repository = Repository::Bazaar.create( | |
|
183 | :project => @project, | |
|
184 | :url => File.join(REPOSITORY_PATH, "author_non_ascii"), | |
|
185 | :identifier => 'author_non_ascii', | |
|
186 | :log_encoding => log_encoding) | |
|
187 | assert repository | |
|
188 | get :annotate, :id => PRJ_ID, :repository_id => 'author_non_ascii', | |
|
189 | :path => repository_path_hash(['author-non-ascii-test.txt'])[:param] | |
|
190 | assert_response :success | |
|
191 | assert_template 'annotate' | |
|
192 | assert_select "th.line-num", :text => '1' do | |
|
193 | assert_select "+ td.revision" do | |
|
194 | assert_select "a", :text => '2' | |
|
195 | assert_select "+ td.author", :text => "test #{CHAR_1_UTF8_HEX}" do | |
|
196 | assert_select "+ td", | |
|
197 | :text => "author non ASCII test" | |
|
204 | 198 | end |
|
205 | 199 | end |
|
206 | 200 | end |
@@ -27,8 +27,7 class RepositoriesFilesystemControllerTest < ActionController::TestCase | |||
|
27 | 27 | PRJ_ID = 3 |
|
28 | 28 | |
|
29 | 29 | def setup |
|
30 | @ruby19_non_utf8_pass = | |
|
31 | (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8') | |
|
30 | @ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8' | |
|
32 | 31 | User.current = nil |
|
33 | 32 | Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem') |
|
34 | 33 | @project = Project.find(PRJ_ID) |
@@ -94,12 +93,11 class RepositoriesFilesystemControllerTest < ActionController::TestCase | |||
|
94 | 93 | :attributes => { :class => 'line-num' }, |
|
95 | 94 | :sibling => { :tag => 'td', :content => /japanese/ } |
|
96 | 95 | if @ruby19_non_utf8_pass |
|
97 |
puts "TODO: show repository file contents test fails |
|
|
98 |
" |
|
|
96 | puts "TODO: show repository file contents test fails " + | |
|
97 | "when Encoding.default_external is not UTF-8. " + | |
|
99 | 98 | "Current value is '#{Encoding.default_external.to_s}'" |
|
100 | 99 | else |
|
101 | str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" | |
|
102 | str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding) | |
|
100 | str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8') | |
|
103 | 101 | assert_tag :tag => 'th', |
|
104 | 102 | :content => '3', |
|
105 | 103 | :attributes => { :class => 'line-num' }, |
@@ -109,7 +107,7 class RepositoriesFilesystemControllerTest < ActionController::TestCase | |||
|
109 | 107 | end |
|
110 | 108 | |
|
111 | 109 | def test_show_utf16 |
|
112 | enc = (RUBY_VERSION == "1.9.2" ? 'UTF-16LE' : 'UTF-16') | |
|
110 | enc = 'UTF-16' | |
|
113 | 111 | with_settings :repositories_encodings => enc do |
|
114 | 112 | get :entry, :id => PRJ_ID, |
|
115 | 113 | :path => repository_path_hash(['japanese', 'utf-16.txt'])[:param] |
@@ -26,8 +26,8 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
26 | 26 | REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s |
|
27 | 27 | REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin? |
|
28 | 28 | PRJ_ID = 3 |
|
29 | CHAR_1_HEX = "\xc3\x9c" | |
|
30 | FELIX_HEX = "Felix Sch\xC3\xA4fer" | |
|
29 | CHAR_1_HEX = "\xc3\x9c".force_encoding('UTF-8') | |
|
30 | FELIX_HEX = "Felix Sch\xC3\xA4fer".force_encoding('UTF-8') | |
|
31 | 31 | NUM_REV = 28 |
|
32 | 32 | |
|
33 | 33 | ## Git, Mercurial and CVS path encodings are binary. |
@@ -39,8 +39,7 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
39 | 39 | JRUBY_SKIP_STR = "TODO: This test fails in JRuby" |
|
40 | 40 | |
|
41 | 41 | def setup |
|
42 | @ruby19_non_utf8_pass = | |
|
43 | (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8') | |
|
42 | @ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8' | |
|
44 | 43 | |
|
45 | 44 | User.current = nil |
|
46 | 45 | @project = Project.find(PRJ_ID) |
@@ -50,12 +49,6 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
50 | 49 | :path_encoding => 'ISO-8859-1' |
|
51 | 50 | ) |
|
52 | 51 | assert @repository |
|
53 | @char_1 = CHAR_1_HEX.dup | |
|
54 | @felix_utf8 = FELIX_HEX.dup | |
|
55 | if @char_1.respond_to?(:force_encoding) | |
|
56 | @char_1.force_encoding('UTF-8') | |
|
57 | @felix_utf8.force_encoding('UTF-8') | |
|
58 | end | |
|
59 | 52 | end |
|
60 | 53 | |
|
61 | 54 | def test_create_and_update |
@@ -231,7 +224,7 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
231 | 224 | with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do |
|
232 | 225 | ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1| |
|
233 | 226 | get :entry, :id => PRJ_ID, |
|
234 |
:path => repository_path_hash(['latin-1-dir', "test-#{ |
|
|
227 | :path => repository_path_hash(['latin-1-dir', "test-#{CHAR_1_HEX}.txt"])[:param], | |
|
235 | 228 | :rev => r1 |
|
236 | 229 | assert_response :success |
|
237 | 230 | assert_template 'entry' |
@@ -239,7 +232,7 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
239 | 232 | :content => '1', |
|
240 | 233 | :attributes => { :class => 'line-num' }, |
|
241 | 234 | :sibling => { :tag => 'td', |
|
242 |
:content => /test-#{ |
|
|
235 | :content => /test-#{CHAR_1_HEX}.txt/ } | |
|
243 | 236 | end |
|
244 | 237 | end |
|
245 | 238 | end |
@@ -419,14 +412,14 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
419 | 412 | :descendant => { |
|
420 | 413 | :tag => 'th', |
|
421 | 414 | :attributes => { :class => 'filename' } , |
|
422 |
:content => /latin-1-dir\/test-#{ |
|
|
415 | :content => /latin-1-dir\/test-#{CHAR_1_HEX}.txt/ , | |
|
423 | 416 | }, |
|
424 | 417 | :sibling => { |
|
425 | 418 | :tag => 'tbody', |
|
426 | 419 | :descendant => { |
|
427 | 420 | :tag => 'td', |
|
428 | 421 | :attributes => { :class => /diff_in/ }, |
|
429 |
:content => /test-#{ |
|
|
422 | :content => /test-#{CHAR_1_HEX}.txt/ | |
|
430 | 423 | } |
|
431 | 424 | } |
|
432 | 425 | end |
@@ -498,11 +491,13 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
498 | 491 | end |
|
499 | 492 | |
|
500 | 493 | def test_annotate_binary_file |
|
501 | get :annotate, :id => PRJ_ID, | |
|
502 | :path => repository_path_hash(['images', 'edit.png'])[:param] | |
|
503 | assert_response 500 | |
|
504 | assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ }, | |
|
505 | :content => /cannot be annotated/ | |
|
494 | with_settings :default_language => 'en' do | |
|
495 | get :annotate, :id => PRJ_ID, | |
|
496 | :path => repository_path_hash(['images', 'edit.png'])[:param] | |
|
497 | assert_response 500 | |
|
498 | assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ }, | |
|
499 | :content => /cannot be annotated/ | |
|
500 | end | |
|
506 | 501 | end |
|
507 | 502 | |
|
508 | 503 | def test_annotate_error_when_too_big |
@@ -533,14 +528,14 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
533 | 528 | with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do |
|
534 | 529 | ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1| |
|
535 | 530 | get :annotate, :id => PRJ_ID, |
|
536 |
:path => repository_path_hash(['latin-1-dir', "test-#{ |
|
|
531 | :path => repository_path_hash(['latin-1-dir', "test-#{CHAR_1_HEX}.txt"])[:param], | |
|
537 | 532 | :rev => r1 |
|
538 | 533 | assert_select "th.line-num", :text => '1' do |
|
539 | 534 | assert_select "+ td.revision" do |
|
540 | 535 | assert_select "a", :text => '57ca437c' |
|
541 | 536 | assert_select "+ td.author", :text => "jsmith" do |
|
542 | 537 | assert_select "+ td", |
|
543 |
:text => "test-#{ |
|
|
538 | :text => "test-#{CHAR_1_HEX}.txt" | |
|
544 | 539 | end |
|
545 | 540 | end |
|
546 | 541 | end |
@@ -557,7 +552,7 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
557 | 552 | assert_select "th.line-num", :text => '1' do |
|
558 | 553 | assert_select "+ td.revision" do |
|
559 | 554 | assert_select "a", :text => '83ca5fd5' |
|
560 |
assert_select "+ td.author", :text => |
|
|
555 | assert_select "+ td.author", :text => FELIX_HEX do | |
|
561 | 556 | assert_select "+ td", |
|
562 | 557 | :text => "And this is a file with a leading and trailing space..." |
|
563 | 558 | end |
@@ -643,8 +638,8 class RepositoriesGitControllerTest < ActionController::TestCase | |||
|
643 | 638 | private |
|
644 | 639 | |
|
645 | 640 | def puts_ruby19_non_utf8_pass |
|
646 |
puts "TODO: This test fails |
|
|
647 |
" |
|
|
641 | puts "TODO: This test fails " + | |
|
642 | "when Encoding.default_external is not UTF-8. " + | |
|
648 | 643 | "Current value is '#{Encoding.default_external.to_s}'" |
|
649 | 644 | end |
|
650 | 645 | else |
@@ -28,8 +28,7 class RepositoriesMercurialControllerTest < ActionController::TestCase | |||
|
28 | 28 | PRJ_ID = 3 |
|
29 | 29 | NUM_REV = 34 |
|
30 | 30 | |
|
31 | ruby19_non_utf8_pass = | |
|
32 | (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8') | |
|
31 | ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8' | |
|
33 | 32 | |
|
34 | 33 | def setup |
|
35 | 34 | User.current = nil |
@@ -41,21 +40,15 class RepositoriesMercurialControllerTest < ActionController::TestCase | |||
|
41 | 40 | ) |
|
42 | 41 | assert @repository |
|
43 | 42 | @diff_c_support = true |
|
44 | @char_1 = CHAR_1_HEX.dup | |
|
45 | @tag_char_1 = "tag-#{CHAR_1_HEX}-00" | |
|
46 | @branch_char_0 = "branch-#{CHAR_1_HEX}-00" | |
|
47 | @branch_char_1 = "branch-#{CHAR_1_HEX}-01" | |
|
48 | if @char_1.respond_to?(:force_encoding) | |
|
49 | @char_1.force_encoding('UTF-8') | |
|
50 | @tag_char_1.force_encoding('UTF-8') | |
|
51 | @branch_char_0.force_encoding('UTF-8') | |
|
52 | @branch_char_1.force_encoding('UTF-8') | |
|
53 | end | |
|
43 | @char_1 = CHAR_1_HEX.dup.force_encoding('UTF-8') | |
|
44 | @tag_char_1 = "tag-#{CHAR_1_HEX}-00".force_encoding('UTF-8') | |
|
45 | @branch_char_0 = "branch-#{CHAR_1_HEX}-00".force_encoding('UTF-8') | |
|
46 | @branch_char_1 = "branch-#{CHAR_1_HEX}-01".force_encoding('UTF-8') | |
|
54 | 47 | end |
|
55 | 48 | |
|
56 | 49 | if ruby19_non_utf8_pass |
|
57 |
puts "TODO: Mercurial functional test fails |
|
|
58 |
" |
|
|
50 | puts "TODO: Mercurial functional test fails " + | |
|
51 | "when Encoding.default_external is not UTF-8. " + | |
|
59 | 52 | "Current value is '#{Encoding.default_external.to_s}'" |
|
60 | 53 | def test_fake; assert true end |
|
61 | 54 | elsif File.directory?(REPOSITORY_PATH) |
@@ -31,7 +31,7 class RolesControllerTest < ActionController::TestCase | |||
|
31 | 31 | assert_template 'index' |
|
32 | 32 | |
|
33 | 33 | assert_not_nil assigns(:roles) |
|
34 |
assert_equal Role.order('builtin, position').a |
|
|
34 | assert_equal Role.order('builtin, position').to_a, assigns(:roles) | |
|
35 | 35 | |
|
36 | 36 | assert_tag :tag => 'a', :attributes => { :href => '/roles/1/edit' }, |
|
37 | 37 | :content => 'Manager' |
@@ -160,7 +160,7 class RolesControllerTest < ActionController::TestCase | |||
|
160 | 160 | assert_template 'permissions' |
|
161 | 161 | |
|
162 | 162 | assert_not_nil assigns(:roles) |
|
163 |
assert_equal Role.order('builtin, position').a |
|
|
163 | assert_equal Role.order('builtin, position').to_a, assigns(:roles) | |
|
164 | 164 | |
|
165 | 165 | assert_tag :tag => 'input', :attributes => { :type => 'checkbox', |
|
166 | 166 | :name => 'permissions[3][]', |
@@ -40,7 +40,9 class SearchControllerTest < ActionController::TestCase | |||
|
40 | 40 | end |
|
41 | 41 | |
|
42 | 42 | def test_search_all_projects |
|
43 | get :index, :q => 'recipe subproject commit', :all_words => '' | |
|
43 | with_settings :default_language => 'en' do | |
|
44 | get :index, :q => 'recipe subproject commit', :all_words => '' | |
|
45 | end | |
|
44 | 46 | assert_response :success |
|
45 | 47 | assert_template 'index' |
|
46 | 48 |
@@ -240,12 +240,8 class TimeEntryReportsControllerTest < ActionController::TestCase | |||
|
240 | 240 | |
|
241 | 241 | def test_csv_big_5 |
|
242 | 242 | Setting.default_language = "zh-TW" |
|
243 | str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88" | |
|
244 | str_big5 = "\xa4@\xa4\xeb" | |
|
245 | if str_utf8.respond_to?(:force_encoding) | |
|
246 | str_utf8.force_encoding('UTF-8') | |
|
247 | str_big5.force_encoding('Big5') | |
|
248 | end | |
|
243 | str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88".force_encoding('UTF-8') | |
|
244 | str_big5 = "\xa4@\xa4\xeb".force_encoding('Big5') | |
|
249 | 245 | user = User.find_by_id(3) |
|
250 | 246 | user.firstname = str_utf8 |
|
251 | 247 | user.lastname = "test-lastname" |
@@ -270,21 +266,14 class TimeEntryReportsControllerTest < ActionController::TestCase | |||
|
270 | 266 | assert_equal 'text/csv; header=present', @response.content_type |
|
271 | 267 | lines = @response.body.chomp.split("\n") |
|
272 | 268 | # Headers |
|
273 | s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp" | |
|
274 | s2 = "\xa4u\xae\xc9\xc1`\xadp" | |
|
275 | if s1.respond_to?(:force_encoding) | |
|
276 | s1.force_encoding('Big5') | |
|
277 | s2.force_encoding('Big5') | |
|
278 | end | |
|
269 | s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5') | |
|
270 | s2 = "\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5') | |
|
279 | 271 | assert_equal s1, lines.first |
|
280 | 272 | # Total row |
|
281 | 273 | assert_equal "#{str_big5} #{user.lastname},7.30,7.30", lines[1] |
|
282 | 274 | assert_equal "#{s2},7.30,7.30", lines[2] |
|
283 | 275 | |
|
284 | str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)" | |
|
285 | if str_tw.respond_to?(:force_encoding) | |
|
286 | str_tw.force_encoding('UTF-8') | |
|
287 | end | |
|
276 | str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)".force_encoding('UTF-8') | |
|
288 | 277 | assert_equal str_tw, l(:general_lang_name) |
|
289 | 278 | assert_equal 'Big5', l(:general_csv_encoding) |
|
290 | 279 | assert_equal ',', l(:general_csv_separator) |
@@ -293,10 +282,7 class TimeEntryReportsControllerTest < ActionController::TestCase | |||
|
293 | 282 | |
|
294 | 283 | def test_csv_cannot_convert_should_be_replaced_big_5 |
|
295 | 284 | Setting.default_language = "zh-TW" |
|
296 | str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85" | |
|
297 | if str_utf8.respond_to?(:force_encoding) | |
|
298 | str_utf8.force_encoding('UTF-8') | |
|
299 | end | |
|
285 | str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8') | |
|
300 | 286 | user = User.find_by_id(3) |
|
301 | 287 | user.firstname = str_utf8 |
|
302 | 288 | user.lastname = "test-lastname" |
@@ -321,21 +307,10 class TimeEntryReportsControllerTest < ActionController::TestCase | |||
|
321 | 307 | assert_equal 'text/csv; header=present', @response.content_type |
|
322 | 308 | lines = @response.body.chomp.split("\n") |
|
323 | 309 | # Headers |
|
324 | s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp" | |
|
325 | if s1.respond_to?(:force_encoding) | |
|
326 | s1.force_encoding('Big5') | |
|
327 | end | |
|
310 | s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5') | |
|
328 | 311 | assert_equal s1, lines.first |
|
329 | 312 | # Total row |
|
330 | s2 = "" | |
|
331 | if s2.respond_to?(:force_encoding) | |
|
332 | s2 = "\xa5H?" | |
|
333 | s2.force_encoding('Big5') | |
|
334 | elsif RUBY_PLATFORM == 'java' | |
|
335 | s2 = "??" | |
|
336 | else | |
|
337 | s2 = "\xa5H???" | |
|
338 | end | |
|
313 | s2 = "\xa5H?".force_encoding('Big5') | |
|
339 | 314 | assert_equal "#{s2} #{user.lastname},7.30,7.30", lines[1] |
|
340 | 315 | end |
|
341 | 316 | |
@@ -362,21 +337,14 class TimeEntryReportsControllerTest < ActionController::TestCase | |||
|
362 | 337 | assert_equal 'text/csv; header=present', @response.content_type |
|
363 | 338 | lines = @response.body.chomp.split("\n") |
|
364 | 339 | # Headers |
|
365 | s1 = "Utilisateur;2011-11-11;Temps total" | |
|
366 | s2 = "Temps total" | |
|
367 | if s1.respond_to?(:force_encoding) | |
|
368 | s1.force_encoding('ISO-8859-1') | |
|
369 | s2.force_encoding('ISO-8859-1') | |
|
370 | end | |
|
340 | s1 = "Utilisateur;2011-11-11;Temps total".force_encoding('ISO-8859-1') | |
|
341 | s2 = "Temps total".force_encoding('ISO-8859-1') | |
|
371 | 342 | assert_equal s1, lines.first |
|
372 | 343 | # Total row |
|
373 | 344 | assert_equal "#{user.firstname} #{user.lastname};7,30;7,30", lines[1] |
|
374 | 345 | assert_equal "#{s2};7,30;7,30", lines[2] |
|
375 | 346 | |
|
376 | str_fr = "Fran\xc3\xa7ais" | |
|
377 | if str_fr.respond_to?(:force_encoding) | |
|
378 | str_fr.force_encoding('UTF-8') | |
|
379 | end | |
|
347 | str_fr = "Fran\xc3\xa7ais".force_encoding('UTF-8') | |
|
380 | 348 | assert_equal str_fr, l(:general_lang_name) |
|
381 | 349 | assert_equal 'ISO-8859-1', l(:general_csv_encoding) |
|
382 | 350 | assert_equal ';', l(:general_csv_separator) |
@@ -702,16 +702,18 class TimelogControllerTest < ActionController::TestCase | |||
|
702 | 702 | end |
|
703 | 703 | |
|
704 | 704 | def test_index_csv_all_projects |
|
705 |
|
|
|
706 | get :index, :format => 'csv' | |
|
707 | assert_response :success | |
|
708 | assert_equal 'text/csv; header=present', response.content_type | |
|
705 | with_settings :date_format => '%m/%d/%Y' do | |
|
706 | get :index, :format => 'csv' | |
|
707 | assert_response :success | |
|
708 | assert_equal 'text/csv; header=present', response.content_type | |
|
709 | end | |
|
709 | 710 | end |
|
710 | 711 | |
|
711 | 712 | def test_index_csv |
|
712 |
|
|
|
713 | get :index, :project_id => 1, :format => 'csv' | |
|
714 | assert_response :success | |
|
715 | assert_equal 'text/csv; header=present', response.content_type | |
|
713 | with_settings :date_format => '%m/%d/%Y' do | |
|
714 | get :index, :project_id => 1, :format => 'csv' | |
|
715 | assert_response :success | |
|
716 | assert_equal 'text/csv; header=present', response.content_type | |
|
717 | end | |
|
716 | 718 | end |
|
717 | 719 | end |
@@ -95,8 +95,8 class TimelogCustomFieldsVisibilityTest < ActionController::TestCase | |||
|
95 | 95 | p1 = Project.generate! |
|
96 | 96 | p2 = Project.generate! |
|
97 | 97 | user = User.generate! |
|
98 |
User.add_to_project(user, p1, Role.where(:id => [1, 3]).a |
|
|
99 |
User.add_to_project(user, p2, Role.where(:id => 3).a |
|
|
98 | User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a) | |
|
99 | User.add_to_project(user, p2, Role.where(:id => 3).to_a) | |
|
100 | 100 | TimeEntry.generate!( |
|
101 | 101 | :issue => Issue.generate!(:project => p1, :tracker_id => 1, |
|
102 | 102 | :custom_field_values => {@field2.id => 'ValueA'})) |
@@ -108,9 +108,9 class TimelogCustomFieldsVisibilityTest < ActionController::TestCase | |||
|
108 | 108 | :custom_field_values => {@field2.id => 'ValueC'})) |
|
109 | 109 | @request.session[:user_id] = user.id |
|
110 | 110 | get :index, :c => ["hours", "issue.cf_#{@field2.id}"] |
|
111 | assert_select 'td', :text => 'ValueA' | |
|
111 | assert_select 'td', {:text => 'ValueA'}, "ValueA not found in:\n#{response.body}" | |
|
112 | 112 | assert_select 'td', :text => 'ValueB', :count => 0 |
|
113 | assert_select 'td', :text => 'ValueC' | |
|
113 | assert_select 'td', {:text => 'ValueC'}, "ValueC not found in:\n#{response.body}" | |
|
114 | 114 | |
|
115 | 115 | get :index, :set_filter => '1', "issue.cf_#{@field2.id}" => '*' |
|
116 | 116 | assert_equal %w(ValueA ValueC), assigns(:entries).map{|i| i.issue.custom_field_value(@field2)}.sort |
@@ -97,9 +97,7 class WelcomeControllerTest < ActionController::TestCase | |||
|
97 | 97 | @request.session[:user_id] = 2 |
|
98 | 98 | |
|
99 | 99 | get :index |
|
100 | assert_tag 'script', | |
|
101 | :attributes => {:type => "text/javascript"}, | |
|
102 | :content => %r{warnLeavingUnsaved} | |
|
100 | assert_select 'script', :text => %r{warnLeavingUnsaved} | |
|
103 | 101 | end |
|
104 | 102 | |
|
105 | 103 | def test_warn_on_leaving_unsaved_turn_off |
@@ -58,7 +58,9 class WikiControllerTest < ActionController::TestCase | |||
|
58 | 58 | end |
|
59 | 59 | |
|
60 | 60 | def test_show_old_version |
|
61 | get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2' | |
|
61 | with_settings :default_language => 'en' do | |
|
62 | get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2' | |
|
63 | end | |
|
62 | 64 | assert_response :success |
|
63 | 65 | assert_template 'show' |
|
64 | 66 | |
@@ -89,7 +91,9 class WikiControllerTest < ActionController::TestCase | |||
|
89 | 91 | end |
|
90 | 92 | |
|
91 | 93 | def test_show_first_version |
|
92 | get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1' | |
|
94 | with_settings :default_language => 'en' do | |
|
95 | get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1' | |
|
96 | end | |
|
93 | 97 | assert_response :success |
|
94 | 98 | assert_template 'show' |
|
95 | 99 |
@@ -248,7 +248,7 class WorkflowsControllerTest < ActionController::TestCase | |||
|
248 | 248 | |
|
249 | 249 | get :permissions, :role_id => 1, :tracker_id => 2, :used_statuses_only => '0' |
|
250 | 250 | assert_response :success |
|
251 |
assert_equal IssueStatus.sorted.a |
|
|
251 | assert_equal IssueStatus.sorted.to_a, assigns(:statuses) | |
|
252 | 252 | end |
|
253 | 253 | |
|
254 | 254 | def test_post_permissions |
@@ -17,13 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 | begin | |
|
21 | require 'mocha/setup' | |
|
22 | rescue | |
|
23 | # Won't run some tests | |
|
24 | end | |
|
25 | ||
|
26 | class AccountTest < ActionController::IntegrationTest | |
|
20 | class AccountTest < ActionDispatch::IntegrationTest | |
|
27 | 21 | fixtures :users, :roles |
|
28 | 22 | |
|
29 | 23 | def test_login |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class AdminTest < Action |
|
|
20 | class AdminTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :projects, :trackers, :issue_statuses, :issues, |
|
22 | 22 | :enumerations, :users, :issue_categories, |
|
23 | 23 | :projects_trackers, |
@@ -41,11 +41,8 class Redmine::ApiTest::AuthenticationTest < Redmine::ApiTest::Base | |||
|
41 | 41 | end |
|
42 | 42 | |
|
43 | 43 | def test_invalid_utf8_credentials_should_not_trigger_an_error |
|
44 | invalid_utf8 = "\x82" | |
|
45 |
|
|
|
46 | invalid_utf8.force_encoding('UTF-8') | |
|
47 | assert !invalid_utf8.valid_encoding? | |
|
48 | end | |
|
44 | invalid_utf8 = "\x82".force_encoding('UTF-8') | |
|
45 | assert !invalid_utf8.valid_encoding? | |
|
49 | 46 | assert_nothing_raised do |
|
50 | 47 | get '/users/current.xml', {}, credentials(invalid_utf8, "foo") |
|
51 | 48 | end |
@@ -165,7 +165,7 class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base | |||
|
165 | 165 | |
|
166 | 166 | assert_response :unprocessable_entity |
|
167 | 167 | assert_equal 'application/xml', @response.content_type |
|
168 |
assert_tag 'errors', :child => {:tag => 'error', :content => / |
|
|
168 | assert_tag 'errors', :child => {:tag => 'error', :content => /role can't be empty/i} | |
|
169 | 169 | end |
|
170 | 170 | |
|
171 | 171 | test "DELETE /memberships/:id.xml should destroy the membership" do |
@@ -195,12 +195,12 class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base | |||
|
195 | 195 | end |
|
196 | 196 | |
|
197 | 197 | test "POST /projects.xml with valid parameters should create the project" do |
|
198 |
|
|
|
199 | ||
|
200 | assert_difference('Project.count') do | |
|
201 | post '/projects.xml', | |
|
202 | {:project => {:name => 'API test', :identifier => 'api-test'}}, | |
|
203 | credentials('admin') | |
|
198 | with_settings :default_projects_modules => ['issue_tracking', 'repository'] do | |
|
199 | assert_difference('Project.count') do | |
|
200 | post '/projects.xml', | |
|
201 | {:project => {:name => 'API test', :identifier => 'api-test'}}, | |
|
202 | credentials('admin') | |
|
203 | end | |
|
204 | 204 | end |
|
205 | 205 | |
|
206 | 206 | project = Project.order('id DESC').first |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class ApplicationTest < Action |
|
|
20 | class ApplicationTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | include Redmine::I18n |
|
22 | 22 | |
|
23 | 23 | fixtures :projects, :trackers, :issue_statuses, :issues, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class AttachmentsTest < Action |
|
|
20 | class AttachmentsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :projects, :enabled_modules, |
|
22 | 22 | :users, :roles, :members, :member_roles, |
|
23 | 23 | :trackers, :projects_trackers, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class FeedsTest < Action |
|
|
20 | class FeedsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :projects, :trackers, :issue_statuses, :issues, |
|
22 | 22 | :enumerations, :users, :issue_categories, |
|
23 | 23 | :projects_trackers, :enabled_modules, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class IssuesTest < Action |
|
|
20 | class IssuesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :projects, |
|
22 | 22 | :users, |
|
23 | 23 | :roles, |
@@ -132,27 +132,27 class IssuesTest < ActionController::IntegrationTest | |||
|
132 | 132 | end |
|
133 | 133 | |
|
134 | 134 | def test_pagination_links_on_index |
|
135 |
|
|
|
136 | get '/projects/ecookbook/issues' | |
|
137 | ||
|
138 | assert_tag :a, :content => '2', | |
|
139 | :attributes => { :href => '/projects/ecookbook/issues?page=2' } | |
|
135 | with_settings :per_page_options => '2' do | |
|
136 | get '/projects/ecookbook/issues' | |
|
140 | 137 | |
|
138 | assert_tag :a, :content => '2', | |
|
139 | :attributes => { :href => '/projects/ecookbook/issues?page=2' } | |
|
140 | end | |
|
141 | 141 | end |
|
142 | 142 | |
|
143 | 143 | def test_pagination_links_on_index_without_project_id_in_url |
|
144 |
|
|
|
145 | get '/issues', :project_id => 'ecookbook' | |
|
146 | ||
|
147 | assert_tag :a, :content => '2', | |
|
148 | :attributes => { :href => '/projects/ecookbook/issues?page=2' } | |
|
149 | ||
|
144 | with_settings :per_page_options => '2' do | |
|
145 | get '/issues', :project_id => 'ecookbook' | |
|
146 | ||
|
147 | assert_tag :a, :content => '2', | |
|
148 | :attributes => { :href => '/projects/ecookbook/issues?page=2' } | |
|
149 | end | |
|
150 | 150 | end |
|
151 | 151 | |
|
152 | 152 | def test_issue_with_user_custom_field |
|
153 | 153 | @field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true, :trackers => Tracker.all) |
|
154 | 154 | Role.anonymous.add_permission! :add_issues, :edit_issues |
|
155 | users = Project.find(1).users | |
|
155 | users = Project.find(1).users.uniq.sort | |
|
156 | 156 | tester = users.first |
|
157 | 157 | |
|
158 | 158 | # Issue form |
@@ -205,8 +205,8 class IssuesTest < ActionController::IntegrationTest | |||
|
205 | 205 | :issue => { |
|
206 | 206 | :custom_field_values => {@field.id.to_s => new_tester.id.to_s} |
|
207 | 207 | } |
|
208 | assert_redirected_to "/issues/#{issue.id}" | |
|
208 | 209 | end |
|
209 | assert_response 302 | |
|
210 | 210 | |
|
211 | 211 | # Issue view |
|
212 | 212 | follow_redirect! |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class LayoutTest < Action |
|
|
20 | class LayoutTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :projects, :trackers, :issue_statuses, :issues, |
|
22 | 22 | :enumerations, :users, :issue_categories, |
|
23 | 23 | :projects_trackers, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class HookTest < Action |
|
|
20 | class HookTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :users, :roles, :projects, :members, :member_roles |
|
22 | 22 | |
|
23 | 23 | # Hooks that are manually registered later |
@@ -34,6 +34,8 class HookTest < ActionController::IntegrationTest | |||
|
34 | 34 | end |
|
35 | 35 | end |
|
36 | 36 | |
|
37 | Redmine::Hook.clear_listeners | |
|
38 | ||
|
37 | 39 | class ContentForInsideHook < Redmine::Hook::ViewListener |
|
38 | 40 | render_on :view_welcome_index_left, :inline => <<-VIEW |
|
39 | 41 | <% content_for :header_tags do %> |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class MenuManagerTest < Action |
|
|
20 | class MenuManagerTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | include Redmine::I18n |
|
22 | 22 | |
|
23 | 23 | fixtures :projects, :trackers, :issue_statuses, :issues, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class ThemesTest < Action |
|
|
20 | class ThemesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | |
|
22 | 22 | def setup |
|
23 | 23 | @theme = Redmine::Themes.themes.last |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class ProjectsTest < Action |
|
|
20 | class ProjectsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :projects, :users, :members, :enabled_modules |
|
22 | 22 | |
|
23 | 23 | def test_archive_project |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RepositoriesGitTest < Action |
|
|
20 | class RepositoriesGitTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
22 | 22 | :repositories, :enabled_modules |
|
23 | 23 |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingAccountTest < Action |
|
|
20 | class RoutingAccountTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_account |
|
22 | 22 | ["get", "post"].each do |method| |
|
23 | 23 | assert_routing( |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingActivitiesTest < Action |
|
|
20 | class RoutingActivitiesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_activities |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/activity" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingAdminTest < Action |
|
|
20 | class RoutingAdminTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_administration_panel |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/admin" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingAttachmentsTest < Action |
|
|
20 | class RoutingAttachmentsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_attachments |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/attachments/1" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingAuthSourcesTest < Action |
|
|
20 | class RoutingAuthSourcesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_auth_sources |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/auth_sources" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingAutoCompletesTest < Action |
|
|
20 | class RoutingAutoCompletesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_auto_completes |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/issues/auto_complete" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingBoardsTest < Action |
|
|
20 | class RoutingBoardsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_boards |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects/world_domination/boards" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingCalendarsTest < Action |
|
|
20 | class RoutingCalendarsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_calendars |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/issues/calendar" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingCommentsTest < Action |
|
|
20 | class RoutingCommentsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_comments |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'post', :path => "/news/567/comments" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingContextMenusTest < Action |
|
|
20 | class RoutingContextMenusTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_context_menus_time_entries |
|
22 | 22 | ["get", "post"].each do |method| |
|
23 | 23 | assert_routing( |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingCustomFieldsTest < Action |
|
|
20 | class RoutingCustomFieldsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_custom_fields |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/custom_fields" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingDocumentsTest < Action |
|
|
20 | class RoutingDocumentsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_documents_scoped_under_project |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects/567/documents" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingEnumerationsTest < Action |
|
|
20 | class RoutingEnumerationsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_enumerations |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/enumerations" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingFilesTest < Action |
|
|
20 | class RoutingFilesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_files |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects/33/files" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingGanttsTest < Action |
|
|
20 | class RoutingGanttsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_gantts |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/issues/gantt" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingGroupsTest < Action |
|
|
20 | class RoutingGroupsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_groups_resources |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/groups" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingIssueCategoriesTest < Action |
|
|
20 | class RoutingIssueCategoriesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_issue_categories_scoped_under_project |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects/foo/issue_categories" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingIssueRelationsTest < Action |
|
|
20 | class RoutingIssueRelationsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_issue_relations |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/issues/1/relations" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingIssueStatusesTest < Action |
|
|
20 | class RoutingIssueStatusesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_issue_statuses |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/issue_statuses" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingIssuesTest < Action |
|
|
20 | class RoutingIssuesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_issues_rest_actions |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/issues" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingJournalsTest < Action |
|
|
20 | class RoutingJournalsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_journals |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'post', :path => "/issues/1/quoted" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingMailHandlerTest < Action |
|
|
20 | class RoutingMailHandlerTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_mail_handler |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => "post", :path => "/mail_handler" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingMembersTest < Action |
|
|
20 | class RoutingMembersTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_members |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects/5234/memberships.xml" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingMessagesTest < Action |
|
|
20 | class RoutingMessagesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_messages |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/boards/22/topics/2" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingMyTest < Action |
|
|
20 | class RoutingMyTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_my |
|
22 | 22 | ["get", "post"].each do |method| |
|
23 | 23 | assert_routing( |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingNewsTest < Action |
|
|
20 | class RoutingNewsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_news_index |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/news" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingPreviewsTest < Action |
|
|
20 | class RoutingPreviewsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_previews |
|
22 | 22 | ["get", "post", "put"].each do |method| |
|
23 | 23 | assert_routing( |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingProjectEnumerationsTest < Action |
|
|
20 | class RoutingProjectEnumerationsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_project_enumerations |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'put', :path => "/projects/64/enumerations" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingProjectsTest < Action |
|
|
20 | class RoutingProjectsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_projects |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingQueriesTest < Action |
|
|
20 | class RoutingQueriesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_queries |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/queries.xml" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingReportsTest < Action |
|
|
20 | class RoutingReportsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_reports |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects/567/issues/report" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingRepositoriesTest < Action |
|
|
20 | class RoutingRepositoriesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def setup |
|
22 | 22 | @path_hash = repository_path_hash(%w[path to file.c]) |
|
23 | 23 | assert_equal "path/to/file.c", @path_hash[:path] |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingRolesTest < Action |
|
|
20 | class RoutingRolesTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_roles |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/roles" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingSearchTest < Action |
|
|
20 | class RoutingSearchTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_search |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/search" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingSettingsTest < Action |
|
|
20 | class RoutingSettingsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_settings |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/settings" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingSysTest < Action |
|
|
20 | class RoutingSysTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_sys |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/sys/projects" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingTimelogsTest < Action |
|
|
20 | class RoutingTimelogsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_timelogs_global |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/time_entries" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingTrackersTest < Action |
|
|
20 | class RoutingTrackersTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_trackers |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/trackers" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingUsersTest < Action |
|
|
20 | class RoutingUsersTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_users |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/users" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingVersionsTest < Action |
|
|
20 | class RoutingVersionsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_roadmap |
|
22 | 22 | # /projects/foo/versions is /projects/foo/roadmap |
|
23 | 23 | assert_routing( |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingWatchersTest < Action |
|
|
20 | class RoutingWatchersTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_watchers |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/watchers/new" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingWelcomeTest < Action |
|
|
20 | class RoutingWelcomeTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_welcome |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingWikiTest < Action |
|
|
20 | class RoutingWikiTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_wiki_matching |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/projects/567/wiki" }, |
@@ -54,7 +54,7 class RoutingWikiTest < ActionController::IntegrationTest | |||
|
54 | 54 | :id => 'CookBook_documentation', :version => '2' } |
|
55 | 55 | ) |
|
56 | 56 | # Make sure we don't route wiki page sub-uris to let plugins handle them |
|
57 | assert_raise(ActionController::RoutingError) do | |
|
57 | assert_raise(Minitest::Assertion) do | |
|
58 | 58 | assert_recognizes({}, {:method => 'get', :path => "/projects/1/wiki/CookBook_documentation/whatever"}) |
|
59 | 59 | end |
|
60 | 60 | end |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingWikisTest < Action |
|
|
20 | class RoutingWikisTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_wikis_plural_admin_setup |
|
22 | 22 | ["get", "post"].each do |method| |
|
23 | 23 | assert_routing( |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class RoutingWorkflowsTest < Action |
|
|
20 | class RoutingWorkflowsTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | def test_workflows |
|
22 | 22 | assert_routing( |
|
23 | 23 | { :method => 'get', :path => "/workflows" }, |
@@ -17,7 +17,7 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class UsersTest < Action |
|
|
20 | class UsersTest < ActionDispatch::IntegrationTest | |
|
21 | 21 | fixtures :users |
|
22 | 22 | |
|
23 | 23 | def test_destroy_should_not_accept_get_requests |
@@ -14,7 +14,7 module ObjectHelpers | |||
|
14 | 14 | |
|
15 | 15 | def User.add_to_project(user, project, roles=nil) |
|
16 | 16 | roles = Role.find(1) if roles.nil? |
|
17 |
roles = [roles] |
|
|
17 | roles = [roles] if roles.is_a?(Role) | |
|
18 | 18 | Member.create!(:principal => user, :project => project, :roles => roles) |
|
19 | 19 | end |
|
20 | 20 | |
@@ -178,14 +178,6 module ObjectHelpers | |||
|
178 | 178 | changeset.save! |
|
179 | 179 | changeset |
|
180 | 180 | end |
|
181 | ||
|
182 | def Query.generate!(attributes={}) | |
|
183 | query = new(attributes) | |
|
184 | query.name = "Generated query" if query.name.blank? | |
|
185 | query.user ||= User.find(1) | |
|
186 | query.save! | |
|
187 | query | |
|
188 | end | |
|
189 | 181 | end |
|
190 | 182 | |
|
191 | 183 | module IssueObjectHelpers |
@@ -26,17 +26,25 include ObjectHelpers | |||
|
26 | 26 | |
|
27 | 27 | require 'awesome_nested_set/version' |
|
28 | 28 | |
|
29 | class ActionView::TestCase | |
|
30 | helper :application | |
|
31 | include ApplicationHelper | |
|
32 | end | |
|
33 | ||
|
29 | 34 | class ActiveSupport::TestCase |
|
30 | 35 | include ActionDispatch::TestProcess |
|
36 | include Shoulda::Context::Assertions | |
|
37 | include Shoulda::Context::InstanceMethods | |
|
38 | extend Shoulda::Context::ClassMethods | |
|
31 | 39 | |
|
32 | 40 | self.use_transactional_fixtures = true |
|
33 | 41 | self.use_instantiated_fixtures = false |
|
34 | 42 | |
|
35 | ESCAPED_CANT = 'can't' | |
|
36 | ESCAPED_UCANT = 'Can't' | |
|
43 | #ESCAPED_CANT = 'can't' | |
|
44 | #ESCAPED_UCANT = 'Can't' | |
|
37 | 45 | # Rails 4.0.2 |
|
38 |
|
|
|
39 |
|
|
|
46 | ESCAPED_CANT = 'can't' | |
|
47 | ESCAPED_UCANT = 'Can't' | |
|
40 | 48 | |
|
41 | 49 | def log_user(login, password) |
|
42 | 50 | User.anonymous |
@@ -147,7 +155,9 class ActiveSupport::TestCase | |||
|
147 | 155 | |
|
148 | 156 | # Returns the path to the test +vendor+ repository |
|
149 | 157 | def self.repository_path(vendor) |
|
150 | Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s | |
|
158 | path = Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s | |
|
159 | # Unlike ruby, JRuby returns Rails.root with backslashes under Windows | |
|
160 | path.tr("\\", "/") | |
|
151 | 161 | end |
|
152 | 162 | |
|
153 | 163 | # Returns the url of the subversion test repository |
@@ -388,8 +388,7 class ChangesetTest < ActiveSupport::TestCase | |||
|
388 | 388 | def test_comments_should_be_converted_to_utf8 |
|
389 | 389 | proj = Project.find(3) |
|
390 | 390 | # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") |
|
391 | str = "Texte encod\xe9 en ISO-8859-1." | |
|
392 | str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding) | |
|
391 | str = "Texte encod\xe9 en ISO-8859-1.".force_encoding("ASCII-8BIT") | |
|
393 | 392 | r = Repository::Bazaar.create!( |
|
394 | 393 | :project => proj, |
|
395 | 394 | :url => '/tmp/test/bazaar', |
@@ -401,18 +400,15 class ChangesetTest < ActiveSupport::TestCase | |||
|
401 | 400 | :scmid => '12345', |
|
402 | 401 | :comments => str) |
|
403 | 402 | assert( c.save ) |
|
404 | str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1." | |
|
405 | str_utf8.force_encoding("UTF-8") if str_utf8.respond_to?(:force_encoding) | |
|
403 | str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1.".force_encoding("UTF-8") | |
|
406 | 404 | assert_equal str_utf8, c.comments |
|
407 | 405 | end |
|
408 | 406 | |
|
409 | 407 | def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1 |
|
410 | 408 | proj = Project.find(3) |
|
411 | 409 | # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") |
|
412 | str1 = "Texte encod\xe9 en ISO-8859-1." | |
|
413 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test" | |
|
414 | str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding) | |
|
415 | str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding) | |
|
410 | str1 = "Texte encod\xe9 en ISO-8859-1.".force_encoding("UTF-8") | |
|
411 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT") | |
|
416 | 412 | r = Repository::Bazaar.create!( |
|
417 | 413 | :project => proj, |
|
418 | 414 | :url => '/tmp/test/bazaar', |
@@ -431,10 +427,7 class ChangesetTest < ActiveSupport::TestCase | |||
|
431 | 427 | |
|
432 | 428 | def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis |
|
433 | 429 | proj = Project.find(3) |
|
434 | str = "test\xb5\xfetest\xb5\xfe" | |
|
435 | if str.respond_to?(:force_encoding) | |
|
436 | str.force_encoding('ASCII-8BIT') | |
|
437 | end | |
|
430 | str = "test\xb5\xfetest\xb5\xfe".force_encoding('ASCII-8BIT') | |
|
438 | 431 | r = Repository::Bazaar.create!( |
|
439 | 432 | :project => proj, |
|
440 | 433 | :url => '/tmp/test/bazaar', |
@@ -453,14 +446,12 class ChangesetTest < ActiveSupport::TestCase | |||
|
453 | 446 | s1 = "\xC2\x80" |
|
454 | 447 | s2 = "\xc3\x82\xc2\x80" |
|
455 | 448 | s4 = s2.dup |
|
456 | if s1.respond_to?(:force_encoding) | |
|
457 | s3 = s1.dup | |
|
458 |
|
|
|
459 |
|
|
|
460 |
|
|
|
461 | s4.force_encoding('UTF-8') | |
|
462 | assert_equal s3.encode('UTF-8'), s4 | |
|
463 | end | |
|
449 | s3 = s1.dup | |
|
450 | s1.force_encoding('ASCII-8BIT') | |
|
451 | s2.force_encoding('ASCII-8BIT') | |
|
452 | s3.force_encoding('ISO-8859-1') | |
|
453 | s4.force_encoding('UTF-8') | |
|
454 | assert_equal s3.encode('UTF-8'), s4 | |
|
464 | 455 | proj = Project.find(3) |
|
465 | 456 | r = Repository::Bazaar.create!( |
|
466 | 457 | :project => proj, |
@@ -478,10 +469,8 class ChangesetTest < ActiveSupport::TestCase | |||
|
478 | 469 | |
|
479 | 470 | def test_invalid_utf8_sequences_in_paths_should_be_replaced |
|
480 | 471 | proj = Project.find(3) |
|
481 | str1 = "Texte encod\xe9 en ISO-8859-1" | |
|
482 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test" | |
|
483 | str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding) | |
|
484 | str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding) | |
|
472 | str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8") | |
|
473 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT") | |
|
485 | 474 | r = Repository::Bazaar.create!( |
|
486 | 475 | :project => proj, |
|
487 | 476 | :url => '/tmp/test/bazaar', |
@@ -521,9 +510,7 class ChangesetTest < ActiveSupport::TestCase | |||
|
521 | 510 | assert( c.save ) |
|
522 | 511 | assert_equal "", c.comments |
|
523 | 512 | assert_equal nil, c.committer |
|
524 | if c.comments.respond_to?(:force_encoding) | |
|
525 | assert_equal "UTF-8", c.comments.encoding.to_s | |
|
526 | end | |
|
513 | assert_equal "UTF-8", c.comments.encoding.to_s | |
|
527 | 514 | end |
|
528 | 515 | |
|
529 | 516 | def test_comments_empty |
@@ -542,10 +529,8 class ChangesetTest < ActiveSupport::TestCase | |||
|
542 | 529 | assert( c.save ) |
|
543 | 530 | assert_equal "", c.comments |
|
544 | 531 | assert_equal "", c.committer |
|
545 | if c.comments.respond_to?(:force_encoding) | |
|
546 |
|
|
|
547 | assert_equal "UTF-8", c.committer.encoding.to_s | |
|
548 | end | |
|
532 | assert_equal "UTF-8", c.comments.encoding.to_s | |
|
533 | assert_equal "UTF-8", c.committer.encoding.to_s | |
|
549 | 534 | end |
|
550 | 535 | |
|
551 | 536 | def test_comments_should_accept_more_than_64k |
@@ -95,14 +95,12 class CustomFieldTest < ActiveSupport::TestCase | |||
|
95 | 95 | assert_equal ["One value", "And another one"], field.possible_values |
|
96 | 96 | end |
|
97 | 97 | |
|
98 | if "string".respond_to?(:encoding) | |
|
99 | def test_possible_values_stored_as_binary_should_be_utf8_encoded | |
|
100 | field = CustomField.find(11) | |
|
101 |
|
|
|
102 |
|
|
|
103 | field.possible_values.each do |value| | |
|
104 | assert_equal "UTF-8", value.encoding.name | |
|
105 | end | |
|
98 | def test_possible_values_stored_as_binary_should_be_utf8_encoded | |
|
99 | field = CustomField.find(11) | |
|
100 | assert_kind_of Array, field.possible_values | |
|
101 | assert field.possible_values.size > 0 | |
|
102 | field.possible_values.each do |value| | |
|
103 | assert_equal "UTF-8", value.encoding.name | |
|
106 | 104 | end |
|
107 | 105 | end |
|
108 | 106 |
@@ -22,7 +22,7 class EnabledModuleTest < ActiveSupport::TestCase | |||
|
22 | 22 | |
|
23 | 23 | def test_enabling_wiki_should_create_a_wiki |
|
24 | 24 | CustomField.delete_all |
|
25 | project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject') | |
|
25 | project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject', :enabled_module_names => []) | |
|
26 | 26 | assert_nil project.wiki |
|
27 | 27 | project.enabled_module_names = ['wiki'] |
|
28 | 28 | project.reload |
@@ -52,8 +52,7 class GroupTest < ActiveSupport::TestCase | |||
|
52 | 52 | |
|
53 | 53 | def test_blank_name_error_message_fr |
|
54 | 54 | set_language_if_valid 'fr' |
|
55 | str = "Nom doit \xc3\xaatre renseign\xc3\xa9(e)" | |
|
56 | str.force_encoding('UTF-8') if str.respond_to?(:force_encoding) | |
|
55 | str = "Nom doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8') | |
|
57 | 56 | g = Group.new |
|
58 | 57 | assert !g.save |
|
59 | 58 | assert_include str, g.errors.full_messages |
@@ -133,20 +132,4 class GroupTest < ActiveSupport::TestCase | |||
|
133 | 132 | |
|
134 | 133 | assert_equal nil, Issue.find(1).assigned_to_id |
|
135 | 134 | end |
|
136 | ||
|
137 | def test_builtin_id_with_anonymous_user_should_return_anonymous_group | |
|
138 | assert_equal 13, Group.builtin_id(User.anonymous) | |
|
139 | end | |
|
140 | ||
|
141 | def test_builtin_id_with_anonymous_role_should_return_anonymous_group | |
|
142 | assert_equal 13, Group.builtin_id(Role.anonymous) | |
|
143 | end | |
|
144 | ||
|
145 | def test_builtin_id_with_user_should_return_non_member_group | |
|
146 | assert_equal 12, Group.builtin_id(User.find(1)) | |
|
147 | end | |
|
148 | ||
|
149 | def test_builtin_id_with_non_member_role_should_return_non_member_group | |
|
150 | assert_equal 12, Group.builtin_id(Role.non_member) | |
|
151 | end | |
|
152 | 135 | end |
@@ -35,10 +35,7 class ApplicationHelperTest < ActionView::TestCase | |||
|
35 | 35 | def setup |
|
36 | 36 | super |
|
37 | 37 | set_tmp_attachments_directory |
|
38 | @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82" | |
|
39 | if @russian_test.respond_to?(:force_encoding) | |
|
40 | @russian_test.force_encoding('UTF-8') | |
|
41 | end | |
|
38 | @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82".force_encoding('UTF-8') | |
|
42 | 39 | end |
|
43 | 40 | |
|
44 | 41 | test "#link_to_if_authorized for authorized user should allow using the :controller and :action for the target link" do |
@@ -99,16 +96,12 class ApplicationHelperTest < ActionView::TestCase | |||
|
99 | 96 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } |
|
100 | 97 | end |
|
101 | 98 | |
|
102 | if 'ruby'.respond_to?(:encoding) | |
|
103 | def test_auto_links_with_non_ascii_characters | |
|
104 | to_test = { | |
|
105 | "http://foo.bar/#{@russian_test}" => | |
|
106 | %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>| | |
|
107 | } | |
|
108 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } | |
|
109 | end | |
|
110 | else | |
|
111 | puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version' | |
|
99 | def test_auto_links_with_non_ascii_characters | |
|
100 | to_test = { | |
|
101 | "http://foo.bar/#{@russian_test}" => | |
|
102 | %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>| | |
|
103 | } | |
|
104 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } | |
|
112 | 105 | end |
|
113 | 106 | |
|
114 | 107 | def test_auto_mailto |
@@ -254,16 +247,12 RAW | |||
|
254 | 247 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } |
|
255 | 248 | end |
|
256 | 249 | |
|
257 | if 'ruby'.respond_to?(:encoding) | |
|
258 | def test_textile_external_links_with_non_ascii_characters | |
|
259 | to_test = { | |
|
260 |
%|This is a |
|
|
261 | %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>| | |
|
262 | } | |
|
263 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } | |
|
264 | end | |
|
265 | else | |
|
266 | puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version' | |
|
250 | def test_textile_external_links_with_non_ascii_characters | |
|
251 | to_test = { | |
|
252 | %|This is a "link":http://foo.bar/#{@russian_test}| => | |
|
253 | %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>| | |
|
254 | } | |
|
255 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } | |
|
267 | 256 | end |
|
268 | 257 | |
|
269 | 258 | def test_redmine_links |
@@ -1336,13 +1325,8 RAW | |||
|
1336 | 1325 | project = Project.find(1) |
|
1337 | 1326 | assert_equal %(<a href="/projects/ecookbook">eCookbook</a>), |
|
1338 | 1327 | link_to_project(project) |
|
1339 | assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>), | |
|
1340 | link_to_project(project, :action => 'settings') | |
|
1341 | 1328 | assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>), |
|
1342 | 1329 | link_to_project(project, {:only_path => false, :jump => 'blah'}) |
|
1343 | result = link_to("eCookbook", "/projects/ecookbook/settings", :class => "project") | |
|
1344 | assert_equal result, | |
|
1345 | link_to_project(project, {:action => 'settings'}, :class => "project") | |
|
1346 | 1330 | end |
|
1347 | 1331 | |
|
1348 | 1332 | def test_link_to_project_settings |
@@ -1433,7 +1417,7 RAW | |||
|
1433 | 1417 | |
|
1434 | 1418 | def test_raw_json_should_escape_closing_tags |
|
1435 | 1419 | s = raw_json(["<foo>bar</foo>"]) |
|
1436 |
assert_ |
|
|
1420 | assert_include '\/foo', s | |
|
1437 | 1421 | end |
|
1438 | 1422 | |
|
1439 | 1423 | def test_raw_json_should_be_html_safe |
@@ -1508,8 +1492,7 RAW | |||
|
1508 | 1492 | end |
|
1509 | 1493 | |
|
1510 | 1494 | def test_truncate_single_line_non_ascii |
|
1511 | ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" | |
|
1512 | ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding) | |
|
1495 | ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8') | |
|
1513 | 1496 | result = truncate_single_line_raw("#{ja}\n#{ja}\n#{ja}", 10) |
|
1514 | 1497 | assert_equal "#{ja} #{ja}...", result |
|
1515 | 1498 | assert !result.html_safe? |
@@ -42,23 +42,16 class ProjectsHelperTest < ActionView::TestCase | |||
|
42 | 42 | def test_link_to_version_within_project |
|
43 | 43 | @project = Project.find(2) |
|
44 | 44 | User.current = User.find(1) |
|
45 |
assert_equal '<a href="/versions/5" |
|
|
45 | assert_equal '<a href="/versions/5">Alpha</a>', link_to_version(Version.find(5)) | |
|
46 | 46 | end |
|
47 | 47 | |
|
48 | 48 | def test_link_to_version |
|
49 | 49 | User.current = User.find(1) |
|
50 |
assert_equal '<a href="/versions/5" |
|
|
51 | end | |
|
52 | ||
|
53 | def test_link_to_version_without_effective_date | |
|
54 | User.current = User.find(1) | |
|
55 | version = Version.find(5) | |
|
56 | version.effective_date = nil | |
|
57 | assert_equal '<a href="/versions/5">Alpha</a>', link_to_version(version) | |
|
50 | assert_equal '<a href="/versions/5">OnlineStore - Alpha</a>', link_to_version(Version.find(5)) | |
|
58 | 51 | end |
|
59 | 52 | |
|
60 | 53 | def test_link_to_private_version |
|
61 | assert_equal 'Alpha', link_to_version(Version.find(5)) | |
|
54 | assert_equal 'OnlineStore - Alpha', link_to_version(Version.find(5)) | |
|
62 | 55 | end |
|
63 | 56 | |
|
64 | 57 | def test_link_to_version_invalid_version |
@@ -71,20 +64,11 class ProjectsHelperTest < ActionView::TestCase | |||
|
71 | 64 | end |
|
72 | 65 | |
|
73 | 66 | def test_format_version_name |
|
74 | assert_equal "0.1", format_version_name(Version.find(1)) | |
|
75 | end | |
|
76 | ||
|
77 | def test_format_version_name_for_shared_version_within_project_should_not_display_project_name | |
|
78 | @project = Project.find(1) | |
|
79 | version = Version.find(1) | |
|
80 | version.sharing = 'system' | |
|
81 | assert_equal "0.1", format_version_name(version) | |
|
67 | assert_equal "eCookbook - 0.1", format_version_name(Version.find(1)) | |
|
82 | 68 | end |
|
83 | 69 | |
|
84 |
def test_format_version_name_for_s |
|
|
85 | version = Version.find(1) | |
|
86 | version.sharing = 'system' | |
|
87 | assert_equal "eCookbook - 0.1", format_version_name(version) | |
|
70 | def test_format_version_name_for_system_version | |
|
71 | assert_equal "OnlineStore - Systemwide visible version", format_version_name(Version.find(7)) | |
|
88 | 72 | end |
|
89 | 73 | |
|
90 | 74 | def test_version_options_for_select_with_no_versions |
@@ -47,21 +47,19 class PatchesTest < ActiveSupport::TestCase | |||
|
47 | 47 | end |
|
48 | 48 | |
|
49 | 49 | # https://github.com/rails/rails/pull/14198/files |
|
50 | if RUBY_VERSION >= "1.9" | |
|
51 | def test_indifferent_select | |
|
52 | hash = ActiveSupport::HashWithIndifferentAccess.new(@symbols).select { |_ ,v| v == 1 } | |
|
53 | assert_equal({ 'a' => 1 }, hash) | |
|
54 | assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ? | |
|
55 | Hash : ActiveSupport::HashWithIndifferentAccess), | |
|
56 | hash | |
|
57 | end | |
|
50 | def test_indifferent_select | |
|
51 | hash = ActiveSupport::HashWithIndifferentAccess.new(@symbols).select { |_ ,v| v == 1 } | |
|
52 | assert_equal({ 'a' => 1 }, hash) | |
|
53 | assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ? | |
|
54 | Hash : ActiveSupport::HashWithIndifferentAccess), | |
|
55 | hash | |
|
56 | end | |
|
58 | 57 | |
|
59 |
|
|
|
60 |
|
|
|
61 |
|
|
|
62 |
|
|
|
63 |
|
|
|
64 | end | |
|
58 | def test_indifferent_select_bang | |
|
59 | indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@symbols) | |
|
60 | indifferent_strings.select! { |_, v| v == 1 } | |
|
61 | assert_equal({ 'a' => 1 }, indifferent_strings) | |
|
62 | assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings | |
|
65 | 63 | end |
|
66 | 64 | |
|
67 | 65 | def test_indifferent_reject |
@@ -77,15 +75,13 class PatchesTest < ActiveSupport::TestCase | |||
|
77 | 75 | assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings |
|
78 | 76 | end |
|
79 | 77 | |
|
80 | if RUBY_VERSION >= "1.9" | |
|
81 | def test_select | |
|
82 |
|
|
|
83 | new_ordered_hash = @ordered_hash.select { true } | |
|
84 | assert_equal @keys, new_ordered_hash.map(&:first) | |
|
85 | assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ? | |
|
86 |
|
|
|
87 | new_ordered_hash | |
|
88 | end | |
|
78 | def test_select | |
|
79 | assert_equal @keys, @ordered_hash.select { true }.map(&:first) | |
|
80 | new_ordered_hash = @ordered_hash.select { true } | |
|
81 | assert_equal @keys, new_ordered_hash.map(&:first) | |
|
82 | assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ? | |
|
83 | Hash : ActiveSupport::OrderedHash), | |
|
84 | new_ordered_hash | |
|
89 | 85 | end |
|
90 | 86 | |
|
91 | 87 | def test_reject |
@@ -416,7 +416,7 class IssueNestedSetTest < ActiveSupport::TestCase | |||
|
416 | 416 | c.reload |
|
417 | 417 | |
|
418 | 418 | assert_equal 5, c.issues.count |
|
419 |
ic1, ic2, ic3, ic4, ic5 = c.issues.order('subject').a |
|
|
419 | ic1, ic2, ic3, ic4, ic5 = c.issues.order('subject').to_a | |
|
420 | 420 | assert ic1.root? |
|
421 | 421 | assert_equal ic1, ic2.parent |
|
422 | 422 | assert_equal ic1, ic3.parent |
@@ -83,7 +83,7 class IssuePriorityTest < ActiveSupport::TestCase | |||
|
83 | 83 | IssuePriority.clear_position_names |
|
84 | 84 | |
|
85 | 85 | IssuePriority.compute_position_names |
|
86 |
assert_equal %w(lowest default high3 high2 highest), IssuePriority.active.a |
|
|
86 | assert_equal %w(lowest default high3 high2 highest), IssuePriority.active.to_a.sort.map(&:position_name) | |
|
87 | 87 | end |
|
88 | 88 | |
|
89 | 89 | def test_compute_position_names_without_default_priority_should_split_priorities |
@@ -91,16 +91,16 class IssuePriorityTest < ActiveSupport::TestCase | |||
|
91 | 91 | IssuePriority.update_all :is_default => false |
|
92 | 92 | |
|
93 | 93 | IssuePriority.compute_position_names |
|
94 |
assert_equal %w(lowest low2 default high2 highest), IssuePriority.active.a |
|
|
94 | assert_equal %w(lowest low2 default high2 highest), IssuePriority.active.to_a.sort.map(&:position_name) | |
|
95 | 95 | end |
|
96 | 96 | |
|
97 | 97 | def test_adding_a_priority_should_update_position_names |
|
98 | 98 | priority = IssuePriority.create!(:name => 'New') |
|
99 |
assert_equal %w(lowest default high4 high3 high2 highest), IssuePriority.active.a |
|
|
99 | assert_equal %w(lowest default high4 high3 high2 highest), IssuePriority.active.to_a.sort.map(&:position_name) | |
|
100 | 100 | end |
|
101 | 101 | |
|
102 | 102 | def test_destroying_a_priority_should_update_position_names |
|
103 | 103 | IssuePriority.find_by_position_name('highest').destroy |
|
104 |
assert_equal %w(lowest default high2 highest), IssuePriority.active.a |
|
|
104 | assert_equal %w(lowest default high2 highest), IssuePriority.active.to_a.sort.map(&:position_name) | |
|
105 | 105 | end |
|
106 | 106 | end |
@@ -112,7 +112,7 class IssueStatusTest < ActiveSupport::TestCase | |||
|
112 | 112 | end |
|
113 | 113 | |
|
114 | 114 | def test_sorted_scope |
|
115 |
assert_equal IssueStatus.all.sort, IssueStatus.sorted.a |
|
|
115 | assert_equal IssueStatus.all.sort, IssueStatus.sorted.to_a | |
|
116 | 116 | end |
|
117 | 117 | |
|
118 | 118 | def test_named_scope |
@@ -204,7 +204,7 class IssueTest < ActiveSupport::TestCase | |||
|
204 | 204 | |
|
205 | 205 | def test_visible_scope_for_anonymous |
|
206 | 206 | # Anonymous user should see issues of public projects only |
|
207 |
issues = Issue.visible(User.anonymous).a |
|
|
207 | issues = Issue.visible(User.anonymous).to_a | |
|
208 | 208 | assert issues.any? |
|
209 | 209 | assert_nil issues.detect {|issue| !issue.project.is_public?} |
|
210 | 210 | assert_nil issues.detect {|issue| issue.is_private?} |
@@ -214,7 +214,7 class IssueTest < ActiveSupport::TestCase | |||
|
214 | 214 | def test_visible_scope_for_anonymous_without_view_issues_permissions |
|
215 | 215 | # Anonymous user should not see issues without permission |
|
216 | 216 | Role.anonymous.remove_permission!(:view_issues) |
|
217 |
issues = Issue.visible(User.anonymous).a |
|
|
217 | issues = Issue.visible(User.anonymous).to_a | |
|
218 | 218 | assert issues.empty? |
|
219 | 219 | assert_visibility_match User.anonymous, issues |
|
220 | 220 | end |
@@ -247,7 +247,7 class IssueTest < ActiveSupport::TestCase | |||
|
247 | 247 | user = User.find(9) |
|
248 | 248 | assert user.projects.empty? |
|
249 | 249 | # Non member user should see issues of public projects only |
|
250 |
issues = Issue.visible(user).a |
|
|
250 | issues = Issue.visible(user).to_a | |
|
251 | 251 | assert issues.any? |
|
252 | 252 | assert_nil issues.detect {|issue| !issue.project.is_public?} |
|
253 | 253 | assert_nil issues.detect {|issue| issue.is_private?} |
@@ -259,7 +259,7 class IssueTest < ActiveSupport::TestCase | |||
|
259 | 259 | Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member') |
|
260 | 260 | user = User.find(9) |
|
261 | 261 | |
|
262 |
issues = Issue.visible(user).a |
|
|
262 | issues = Issue.visible(user).to_a | |
|
263 | 263 | assert issues.any? |
|
264 | 264 | assert_nil issues.detect {|issue| issue.author != user} |
|
265 | 265 | assert_visibility_match user, issues |
@@ -270,7 +270,7 class IssueTest < ActiveSupport::TestCase | |||
|
270 | 270 | Role.non_member.remove_permission!(:view_issues) |
|
271 | 271 | user = User.find(9) |
|
272 | 272 | assert user.projects.empty? |
|
273 |
issues = Issue.visible(user).a |
|
|
273 | issues = Issue.visible(user).to_a | |
|
274 | 274 | assert issues.empty? |
|
275 | 275 | assert_visibility_match user, issues |
|
276 | 276 | end |
@@ -291,7 +291,7 class IssueTest < ActiveSupport::TestCase | |||
|
291 | 291 | # User should see issues of projects for which user has view_issues permissions only |
|
292 | 292 | Role.non_member.remove_permission!(:view_issues) |
|
293 | 293 | Member.create!(:principal => user, :project_id => 3, :role_ids => [2]) |
|
294 |
issues = Issue.visible(user).a |
|
|
294 | issues = Issue.visible(user).to_a | |
|
295 | 295 | assert issues.any? |
|
296 | 296 | assert_nil issues.detect {|issue| issue.project_id != 3} |
|
297 | 297 | assert_nil issues.detect {|issue| issue.is_private?} |
@@ -311,12 +311,12 class IssueTest < ActiveSupport::TestCase | |||
|
311 | 311 | :is_private => true) |
|
312 | 312 | |
|
313 | 313 | Role.find(2).update_attribute :issues_visibility, 'default' |
|
314 |
issues = Issue.visible(User.find(8)).a |
|
|
314 | issues = Issue.visible(User.find(8)).to_a | |
|
315 | 315 | assert issues.any? |
|
316 | 316 | assert issues.include?(issue) |
|
317 | 317 | |
|
318 | 318 | Role.find(2).update_attribute :issues_visibility, 'own' |
|
319 |
issues = Issue.visible(User.find(8)).a |
|
|
319 | issues = Issue.visible(User.find(8)).to_a | |
|
320 | 320 | assert issues.any? |
|
321 | 321 | assert issues.include?(issue) |
|
322 | 322 | end |
@@ -325,7 +325,7 class IssueTest < ActiveSupport::TestCase | |||
|
325 | 325 | user = User.find(1) |
|
326 | 326 | user.members.each(&:destroy) |
|
327 | 327 | assert user.projects.empty? |
|
328 |
issues = Issue.visible(user).a |
|
|
328 | issues = Issue.visible(user).to_a | |
|
329 | 329 | assert issues.any? |
|
330 | 330 | # Admin should see issues on private projects that admin does not belong to |
|
331 | 331 | assert issues.detect {|issue| !issue.project.is_public?} |
@@ -336,7 +336,7 class IssueTest < ActiveSupport::TestCase | |||
|
336 | 336 | |
|
337 | 337 | def test_visible_scope_with_project |
|
338 | 338 | project = Project.find(1) |
|
339 |
issues = Issue.visible(User.find(2), :project => project).a |
|
|
339 | issues = Issue.visible(User.find(2), :project => project).to_a | |
|
340 | 340 | projects = issues.collect(&:project).uniq |
|
341 | 341 | assert_equal 1, projects.size |
|
342 | 342 | assert_equal project, projects.first |
@@ -344,7 +344,7 class IssueTest < ActiveSupport::TestCase | |||
|
344 | 344 | |
|
345 | 345 | def test_visible_scope_with_project_and_subprojects |
|
346 | 346 | project = Project.find(1) |
|
347 |
issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).a |
|
|
347 | issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a | |
|
348 | 348 | projects = issues.collect(&:project).uniq |
|
349 | 349 | assert projects.size > 1 |
|
350 | 350 | assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)} |
@@ -370,13 +370,20 class IssueTest < ActiveSupport::TestCase | |||
|
370 | 370 | assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size |
|
371 | 371 | end |
|
372 | 372 | |
|
373 | def test_visible_scope_with_unsaved_user_should_not_raise_an_error | |
|
374 | user = User.new | |
|
375 | assert_nothing_raised do | |
|
376 | Issue.visible(user).to_a | |
|
377 | end | |
|
378 | end | |
|
379 | ||
|
373 | 380 | def test_open_scope |
|
374 |
issues = Issue.open.a |
|
|
381 | issues = Issue.open.to_a | |
|
375 | 382 | assert_nil issues.detect(&:closed?) |
|
376 | 383 | end |
|
377 | 384 | |
|
378 | 385 | def test_open_scope_with_arg |
|
379 |
issues = Issue.open(false).a |
|
|
386 | issues = Issue.open(false).to_a | |
|
380 | 387 | assert_equal issues, issues.select(&:closed?) |
|
381 | 388 | end |
|
382 | 389 | |
@@ -1289,7 +1296,7 class IssueTest < ActiveSupport::TestCase | |||
|
1289 | 1296 | end |
|
1290 | 1297 | |
|
1291 | 1298 | test "#copy should not create a journal" do |
|
1292 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3) | |
|
1299 | copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false) | |
|
1293 | 1300 | copy.save! |
|
1294 | 1301 | assert_equal 0, copy.reload.journals.size |
|
1295 | 1302 | end |
@@ -1325,7 +1332,7 class IssueTest < ActiveSupport::TestCase | |||
|
1325 | 1332 | test "#copy should create a journal with notes" do |
|
1326 | 1333 | date = Date.today |
|
1327 | 1334 | notes = "Notes added when copying" |
|
1328 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date) | |
|
1335 | copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false) | |
|
1329 | 1336 | copy.init_journal(User.current, notes) |
|
1330 | 1337 | copy.save! |
|
1331 | 1338 | |
@@ -1619,13 +1626,15 class IssueTest < ActiveSupport::TestCase | |||
|
1619 | 1626 | issue2.reload |
|
1620 | 1627 | assert_equal Date.parse('2012-10-18'), issue2.start_date |
|
1621 | 1628 | |
|
1622 | child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16', | |
|
1623 | :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1) | |
|
1624 | assert !child.valid? | |
|
1625 | assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages | |
|
1626 | assert_equal Date.parse('2012-10-18'), child.soonest_start | |
|
1627 | child.start_date = '2012-10-18' | |
|
1628 | assert child.save | |
|
1629 | with_settings :date_format => '%m/%d/%Y' do | |
|
1630 | child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16', | |
|
1631 | :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1) | |
|
1632 | assert !child.valid? | |
|
1633 | assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages | |
|
1634 | assert_equal Date.parse('2012-10-18'), child.soonest_start | |
|
1635 | child.start_date = '2012-10-18' | |
|
1636 | assert child.save | |
|
1637 | end | |
|
1629 | 1638 | end |
|
1630 | 1639 | |
|
1631 | 1640 | def test_setting_parent_to_a_dependent_issue_should_not_validate |
@@ -27,6 +27,7 class JournalTest < ActiveSupport::TestCase | |||
|
27 | 27 | |
|
28 | 28 | def setup |
|
29 | 29 | @journal = Journal.find 1 |
|
30 | User.current = nil | |
|
30 | 31 | end |
|
31 | 32 | |
|
32 | 33 | def test_journalized_is_an_issue |
@@ -119,12 +120,12 class JournalTest < ActiveSupport::TestCase | |||
|
119 | 120 | |
|
120 | 121 | def test_visible_scope_for_anonymous |
|
121 | 122 | # Anonymous user should see issues of public projects only |
|
122 |
journals = Journal.visible(User.anonymous).a |
|
|
123 | journals = Journal.visible(User.anonymous).to_a | |
|
123 | 124 | assert journals.any? |
|
124 | 125 | assert_nil journals.detect {|journal| !journal.issue.project.is_public?} |
|
125 | 126 | # Anonymous user should not see issues without permission |
|
126 | 127 | Role.anonymous.remove_permission!(:view_issues) |
|
127 |
journals = Journal.visible(User.anonymous).a |
|
|
128 | journals = Journal.visible(User.anonymous).to_a | |
|
128 | 129 | assert journals.empty? |
|
129 | 130 | end |
|
130 | 131 | |
@@ -132,18 +133,18 class JournalTest < ActiveSupport::TestCase | |||
|
132 | 133 | user = User.find(9) |
|
133 | 134 | assert user.projects.empty? |
|
134 | 135 | # Non member user should see issues of public projects only |
|
135 |
journals = Journal.visible(user).a |
|
|
136 | journals = Journal.visible(user).to_a | |
|
136 | 137 | assert journals.any? |
|
137 | 138 | assert_nil journals.detect {|journal| !journal.issue.project.is_public?} |
|
138 | 139 | # Non member user should not see issues without permission |
|
139 | 140 | Role.non_member.remove_permission!(:view_issues) |
|
140 | 141 | user.reload |
|
141 |
journals = Journal.visible(user).a |
|
|
142 | journals = Journal.visible(user).to_a | |
|
142 | 143 | assert journals.empty? |
|
143 | 144 | # User should see issues of projects for which user has view_issues permissions only |
|
144 | 145 | Member.create!(:principal => user, :project_id => 1, :role_ids => [1]) |
|
145 | 146 | user.reload |
|
146 |
journals = Journal.visible(user).a |
|
|
147 | journals = Journal.visible(user).to_a | |
|
147 | 148 | assert journals.any? |
|
148 | 149 | assert_nil journals.detect {|journal| journal.issue.project_id != 1} |
|
149 | 150 | end |
@@ -152,7 +153,7 class JournalTest < ActiveSupport::TestCase | |||
|
152 | 153 | user = User.find(1) |
|
153 | 154 | user.members.each(&:destroy) |
|
154 | 155 | assert user.projects.empty? |
|
155 |
journals = Journal.visible(user).a |
|
|
156 | journals = Journal.visible(user).to_a | |
|
156 | 157 | assert journals.any? |
|
157 | 158 | # Admin should see issues on private projects that admin does not belong to |
|
158 | 159 | assert journals.detect {|journal| !journal.issue.project.is_public?} |
@@ -21,14 +21,9 class Redmine::CodesetUtilTest < ActiveSupport::TestCase | |||
|
21 | 21 | |
|
22 | 22 | def test_to_utf8_by_setting_from_latin1 |
|
23 | 23 | with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do |
|
24 | s1 = "Texte encod\xc3\xa9" | |
|
25 | s2 = "Texte encod\xe9" | |
|
26 | s3 = s2.dup | |
|
27 | if s1.respond_to?(:force_encoding) | |
|
28 | s1.force_encoding("UTF-8") | |
|
29 | s2.force_encoding("ASCII-8BIT") | |
|
30 | s3.force_encoding("UTF-8") | |
|
31 | end | |
|
24 | s1 = "Texte encod\xc3\xa9".force_encoding("UTF-8") | |
|
25 | s2 = "Texte encod\xe9".force_encoding("ASCII-8BIT") | |
|
26 | s3 = s2.dup.force_encoding("UTF-8") | |
|
32 | 27 | assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2) |
|
33 | 28 | assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3) |
|
34 | 29 | end |
@@ -36,14 +31,9 class Redmine::CodesetUtilTest < ActiveSupport::TestCase | |||
|
36 | 31 | |
|
37 | 32 | def test_to_utf8_by_setting_from_euc_jp |
|
38 | 33 | with_settings :repositories_encodings => 'UTF-8,EUC-JP' do |
|
39 | s1 = "\xe3\x83\xac\xe3\x83\x83\xe3\x83\x89\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xb3" | |
|
40 | s2 = "\xa5\xec\xa5\xc3\xa5\xc9\xa5\xde\xa5\xa4\xa5\xf3" | |
|
41 | s3 = s2.dup | |
|
42 | if s1.respond_to?(:force_encoding) | |
|
43 | s1.force_encoding("UTF-8") | |
|
44 | s2.force_encoding("ASCII-8BIT") | |
|
45 | s3.force_encoding("UTF-8") | |
|
46 | end | |
|
34 | s1 = "\xe3\x83\xac\xe3\x83\x83\xe3\x83\x89\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xb3".force_encoding("UTF-8") | |
|
35 | s2 = "\xa5\xec\xa5\xc3\xa5\xc9\xa5\xde\xa5\xa4\xa5\xf3".force_encoding("ASCII-8BIT") | |
|
36 | s3 = s2.dup.force_encoding("UTF-8") | |
|
47 | 37 | assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2) |
|
48 | 38 | assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3) |
|
49 | 39 | end |
@@ -51,14 +41,9 class Redmine::CodesetUtilTest < ActiveSupport::TestCase | |||
|
51 | 41 | |
|
52 | 42 | def test_to_utf8_by_setting_should_be_converted_all_latin1 |
|
53 | 43 | with_settings :repositories_encodings => 'ISO-8859-1' do |
|
54 | s1 = "\xc3\x82\xc2\x80" | |
|
55 | s2 = "\xC2\x80" | |
|
56 | s3 = s2.dup | |
|
57 | if s1.respond_to?(:force_encoding) | |
|
58 | s1.force_encoding("UTF-8") | |
|
59 | s2.force_encoding("ASCII-8BIT") | |
|
60 | s3.force_encoding("UTF-8") | |
|
61 | end | |
|
44 | s1 = "\xc3\x82\xc2\x80".force_encoding("UTF-8") | |
|
45 | s2 = "\xC2\x80".force_encoding("ASCII-8BIT") | |
|
46 | s3 = s2.dup.force_encoding("UTF-8") | |
|
62 | 47 | assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2) |
|
63 | 48 | assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3) |
|
64 | 49 | end |
@@ -70,45 +55,33 class Redmine::CodesetUtilTest < ActiveSupport::TestCase | |||
|
70 | 55 | end |
|
71 | 56 | |
|
72 | 57 | def test_to_utf8_by_setting_returns_ascii_as_utf8 |
|
73 | s1 = "ASCII" | |
|
74 | s2 = s1.dup | |
|
75 | if s1.respond_to?(:force_encoding) | |
|
76 | s1.force_encoding("UTF-8") | |
|
77 | s2.force_encoding("ISO-8859-1") | |
|
78 | end | |
|
58 | s1 = "ASCII".force_encoding("UTF-8") | |
|
59 | s2 = s1.dup.force_encoding("ISO-8859-1") | |
|
79 | 60 | str1 = Redmine::CodesetUtil.to_utf8_by_setting(s1) |
|
80 | 61 | str2 = Redmine::CodesetUtil.to_utf8_by_setting(s2) |
|
81 | 62 | assert_equal s1, str1 |
|
82 | 63 | assert_equal s1, str2 |
|
83 | if s1.respond_to?(:force_encoding) | |
|
84 |
|
|
|
85 | assert_equal "UTF-8", str2.encoding.to_s | |
|
86 | end | |
|
64 | assert_equal "UTF-8", str1.encoding.to_s | |
|
65 | assert_equal "UTF-8", str2.encoding.to_s | |
|
87 | 66 | end |
|
88 | 67 | |
|
89 | 68 | def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped |
|
90 | 69 | with_settings :repositories_encodings => '' do |
|
91 | 70 | # s1 = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") |
|
92 | s1 = "Texte encod\xe9 en ISO-8859-1." | |
|
93 | s1.force_encoding("ASCII-8BIT") if s1.respond_to?(:force_encoding) | |
|
71 | s1 = "Texte encod\xe9 en ISO-8859-1.".force_encoding("ASCII-8BIT") | |
|
94 | 72 | str = Redmine::CodesetUtil.to_utf8_by_setting(s1) |
|
95 | if str.respond_to?(:force_encoding) | |
|
96 |
|
|
|
97 | assert_equal "UTF-8", str.encoding.to_s | |
|
98 | end | |
|
73 | assert str.valid_encoding? | |
|
74 | assert_equal "UTF-8", str.encoding.to_s | |
|
99 | 75 | assert_equal "Texte encod? en ISO-8859-1.", str |
|
100 | 76 | end |
|
101 | 77 | end |
|
102 | 78 | |
|
103 | 79 | def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped_ja_jis |
|
104 | 80 | with_settings :repositories_encodings => 'ISO-2022-JP' do |
|
105 | s1 = "test\xb5\xfetest\xb5\xfe" | |
|
106 | s1.force_encoding("ASCII-8BIT") if s1.respond_to?(:force_encoding) | |
|
81 | s1 = "test\xb5\xfetest\xb5\xfe".force_encoding("ASCII-8BIT") | |
|
107 | 82 | str = Redmine::CodesetUtil.to_utf8_by_setting(s1) |
|
108 | if str.respond_to?(:force_encoding) | |
|
109 |
|
|
|
110 | assert_equal "UTF-8", str.encoding.to_s | |
|
111 | end | |
|
83 | assert str.valid_encoding? | |
|
84 | assert_equal "UTF-8", str.encoding.to_s | |
|
112 | 85 | assert_equal "test??test??", str |
|
113 | 86 | end |
|
114 | 87 | end |
@@ -27,11 +27,10 class PdfTest < ActiveSupport::TestCase | |||
|
27 | 27 | end |
|
28 | 28 | |
|
29 | 29 | def test_rdm_pdf_iconv_cannot_convert_ja_cp932 |
|
30 | encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" ) | |
|
31 | 30 | utf8_txt_1 = "\xe7\x8b\x80\xe6\x85\x8b" |
|
32 | 31 | utf8_txt_2 = "\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80" |
|
33 | 32 | utf8_txt_3 = "\xe7\x8b\x80\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80" |
|
34 | if utf8_txt_1.respond_to?(:force_encoding) | |
|
33 | ["CP932", "SJIS"].each do |encoding| | |
|
35 | 34 | txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding) |
|
36 | 35 | txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding) |
|
37 | 36 | txt_3 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding) |
@@ -41,88 +40,65 class PdfTest < ActiveSupport::TestCase | |||
|
41 | 40 | assert_equal "ASCII-8BIT", txt_1.encoding.to_s |
|
42 | 41 | assert_equal "ASCII-8BIT", txt_2.encoding.to_s |
|
43 | 42 | assert_equal "ASCII-8BIT", txt_3.encoding.to_s |
|
44 | elsif RUBY_PLATFORM == 'java' | |
|
45 | assert_equal "??", | |
|
46 | Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding) | |
|
47 | assert_equal "???", | |
|
48 | Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding) | |
|
49 | assert_equal "????", | |
|
50 | Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding) | |
|
51 | else | |
|
52 | assert_equal "???\x91\xd4", | |
|
53 | Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding) | |
|
54 | assert_equal "???\x91\xd4???", | |
|
55 | Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding) | |
|
56 | assert_equal "??????\x91\xd4???", | |
|
57 | Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding) | |
|
58 | 43 | end |
|
59 | 44 | end |
|
60 | 45 | |
|
61 | 46 | def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_en |
|
62 | str1 = "Texte encod\xe9 en ISO-8859-1" | |
|
63 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test" | |
|
64 | str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding) | |
|
65 | str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding) | |
|
47 | str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8") | |
|
48 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT") | |
|
66 | 49 | txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, 'UTF-8') |
|
67 | 50 | txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, 'UTF-8') |
|
68 | if txt_1.respond_to?(:force_encoding) | |
|
69 |
|
|
|
70 | assert_equal "ASCII-8BIT", txt_2.encoding.to_s | |
|
71 | end | |
|
51 | assert_equal "ASCII-8BIT", txt_1.encoding.to_s | |
|
52 | assert_equal "ASCII-8BIT", txt_2.encoding.to_s | |
|
72 | 53 | assert_equal "Texte encod? en ISO-8859-1", txt_1 |
|
73 | 54 | assert_equal "?a?b?c?d?e test", txt_2 |
|
74 | 55 | end |
|
75 | 56 | |
|
76 | 57 | def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja |
|
77 | str1 = "Texte encod\xe9 en ISO-8859-1" | |
|
78 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test" | |
|
79 | str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding) | |
|
80 | str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding) | |
|
58 | str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8") | |
|
59 | str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT") | |
|
81 | 60 | encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" ) |
|
82 | 61 | txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, encoding) |
|
83 | 62 | txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, encoding) |
|
84 | if txt_1.respond_to?(:force_encoding) | |
|
85 |
|
|
|
86 | assert_equal "ASCII-8BIT", txt_2.encoding.to_s | |
|
87 | end | |
|
63 | assert_equal "ASCII-8BIT", txt_1.encoding.to_s | |
|
64 | assert_equal "ASCII-8BIT", txt_2.encoding.to_s | |
|
88 | 65 | assert_equal "Texte encod? en ISO-8859-1", txt_1 |
|
89 | 66 | assert_equal "?a?b?c?d?e test", txt_2 |
|
90 | 67 | end |
|
91 | 68 | |
|
92 | 69 | def test_attach |
|
93 | set_fixtures_attachments_directory | |
|
70 | ["CP932", "SJIS"].each do |encoding| | |
|
71 | set_fixtures_attachments_directory | |
|
94 | 72 | |
|
95 | str2 = "\x83e\x83X\x83g" | |
|
96 | str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding) | |
|
97 | encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" ) | |
|
73 | str2 = "\x83e\x83X\x83g".force_encoding("ASCII-8BIT") | |
|
98 | 74 | |
|
99 | a1 = Attachment.find(17) | |
|
100 | a2 = Attachment.find(19) | |
|
75 | a1 = Attachment.find(17) | |
|
76 | a2 = Attachment.find(19) | |
|
77 | User.current = User.find(1) | |
|
78 | assert a1.readable? | |
|
79 | assert a1.visible? | |
|
80 | assert a2.readable? | |
|
81 | assert a2.visible? | |
|
101 | 82 | |
|
102 | User.current = User.find(1) | |
|
103 | assert a1.readable? | |
|
104 | assert a1.visible? | |
|
105 | assert a2.readable? | |
|
106 | assert a2.visible? | |
|
83 | aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8") | |
|
84 | assert_not_nil aa1 | |
|
85 | assert_equal 17, aa1.id | |
|
107 | 86 | |
|
108 |
|
|
|
109 |
assert_not_nil aa |
|
|
110 |
assert_equal 1 |
|
|
111 | aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding) | |
|
112 | assert_not_nil aa2 | |
|
113 | assert_equal 19, aa2.id | |
|
87 | aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding) | |
|
88 | assert_not_nil aa2 | |
|
89 | assert_equal 19, aa2.id | |
|
114 | 90 | |
|
115 | User.current = nil | |
|
116 | assert a1.readable? | |
|
117 | assert (! a1.visible?) | |
|
118 | assert a2.readable? | |
|
119 | assert (! a2.visible?) | |
|
91 | User.current = nil | |
|
92 | assert a1.readable? | |
|
93 | assert (! a1.visible?) | |
|
94 | assert a2.readable? | |
|
95 | assert (! a2.visible?) | |
|
96 | aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8") | |
|
97 | assert_equal nil, aa1 | |
|
98 | aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding) | |
|
99 | assert_equal nil, aa2 | |
|
120 | 100 | |
|
121 | aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8") | |
|
122 | assert_equal nil, aa1 | |
|
123 | aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding) | |
|
124 | assert_equal nil, aa2 | |
|
125 | ||
|
126 | set_tmp_attachments_directory | |
|
101 | set_tmp_attachments_directory | |
|
102 | end | |
|
127 | 103 | end |
|
128 | 104 | end |
@@ -66,6 +66,7 class Redmine::Hook::ManagerTest < ActionView::TestCase | |||
|
66 | 66 | |
|
67 | 67 | def setup |
|
68 | 68 | @hook_module = Redmine::Hook |
|
69 | @hook_module.clear_listeners | |
|
69 | 70 | end |
|
70 | 71 | |
|
71 | 72 | def teardown |
@@ -32,47 +32,50 class Redmine::I18nTest < ActiveSupport::TestCase | |||
|
32 | 32 | def test_date_format_default |
|
33 | 33 | set_language_if_valid 'en' |
|
34 | 34 | today = Date.today |
|
35 |
|
|
|
36 | assert_equal I18n.l(today), format_date(today) | |
|
35 | with_settings :date_format => '' do | |
|
36 | assert_equal I18n.l(today), format_date(today) | |
|
37 | end | |
|
37 | 38 | end |
|
38 | 39 | |
|
39 | 40 | def test_date_format |
|
40 | 41 | set_language_if_valid 'en' |
|
41 | 42 | today = Date.today |
|
42 |
|
|
|
43 | assert_equal today.strftime('%d %m %Y'), format_date(today) | |
|
43 | with_settings :date_format => '%d %m %Y' do | |
|
44 | assert_equal today.strftime('%d %m %Y'), format_date(today) | |
|
45 | end | |
|
44 | 46 | end |
|
45 | 47 | |
|
46 | 48 | def test_date_format_default_with_user_locale |
|
47 | 49 | set_language_if_valid 'es' |
|
48 | 50 | today = now = Time.parse('2011-02-20 14:00:00') |
|
49 |
|
|
|
50 | User.current.language = 'fr' | |
|
51 | s1 = "20 f\xc3\xa9vrier 2011" | |
|
52 | s1.force_encoding("UTF-8") if s1.respond_to?(:force_encoding) | |
|
53 | assert_equal s1, format_date(today) | |
|
54 | User.current.language = nil | |
|
55 | assert_equal '20 Febrero 2011', format_date(today) | |
|
51 | with_settings :date_format => '%d %B %Y' do | |
|
52 | User.current.language = 'fr' | |
|
53 | s1 = "20 f\xc3\xa9vrier 2011".force_encoding("UTF-8") | |
|
54 | assert_equal s1, format_date(today) | |
|
55 | User.current.language = nil | |
|
56 | assert_equal '20 Febrero 2011', format_date(today) | |
|
57 | end | |
|
56 | 58 | end |
|
57 | 59 | |
|
58 | 60 | def test_date_and_time_for_each_language |
|
59 |
|
|
|
60 | valid_languages.each do |lang| | |
|
61 | set_language_if_valid lang | |
|
62 | assert_nothing_raised "#{lang} failure" do | |
|
63 | format_date(Date.today) | |
|
64 | format_time(Time.now) | |
|
65 | format_time(Time.now, false) | |
|
66 | assert_not_equal 'default', ::I18n.l(Date.today, :format => :default), | |
|
67 | "date.formats.default missing in #{lang}" | |
|
68 | assert_not_equal 'time', ::I18n.l(Time.now, :format => :time), | |
|
69 | "time.formats.time missing in #{lang}" | |
|
61 | with_settings :date_format => '' do | |
|
62 | valid_languages.each do |lang| | |
|
63 | set_language_if_valid lang | |
|
64 | assert_nothing_raised "#{lang} failure" do | |
|
65 | format_date(Date.today) | |
|
66 | format_time(Time.now) | |
|
67 | format_time(Time.now, false) | |
|
68 | assert_not_equal 'default', ::I18n.l(Date.today, :format => :default), | |
|
69 | "date.formats.default missing in #{lang}" | |
|
70 | assert_not_equal 'time', ::I18n.l(Time.now, :format => :time), | |
|
71 | "time.formats.time missing in #{lang}" | |
|
72 | end | |
|
73 | assert l('date.day_names').is_a?(Array) | |
|
74 | assert_equal 7, l('date.day_names').size | |
|
75 | ||
|
76 | assert l('date.month_names').is_a?(Array) | |
|
77 | assert_equal 13, l('date.month_names').size | |
|
70 | 78 | end |
|
71 | assert l('date.day_names').is_a?(Array) | |
|
72 | assert_equal 7, l('date.day_names').size | |
|
73 | ||
|
74 | assert l('date.month_names').is_a?(Array) | |
|
75 | assert_equal 13, l('date.month_names').size | |
|
76 | 79 | end |
|
77 | 80 | end |
|
78 | 81 | |
@@ -134,10 +137,10 class Redmine::I18nTest < ActiveSupport::TestCase | |||
|
134 | 137 | def test_utc_time_format |
|
135 | 138 | set_language_if_valid 'en' |
|
136 | 139 | now = Time.now |
|
137 |
|
|
|
138 | Setting.time_format = '%H %M' | |
|
139 |
assert_equal now.strftime('% |
|
|
140 | assert_equal now.strftime('%H %M'), format_time(now.utc, false) | |
|
140 | with_settings :date_format => '%d %m %Y', :time_format => '%H %M' do | |
|
141 | assert_equal now.strftime('%d %m %Y %H %M'), format_time(now.utc) | |
|
142 | assert_equal now.strftime('%H %M'), format_time(now.utc, false) | |
|
143 | end | |
|
141 | 144 | end |
|
142 | 145 | |
|
143 | 146 | def test_number_to_human_size_for_each_language |
@@ -175,8 +178,7 class Redmine::I18nTest < ActiveSupport::TestCase | |||
|
175 | 178 | set_language_if_valid 'bs' |
|
176 | 179 | assert_equal "KM -1000,20", number_to_currency(-1000.2) |
|
177 | 180 | set_language_if_valid 'de' |
|
178 | euro_sign = "\xe2\x82\xac" | |
|
179 | euro_sign.force_encoding('UTF-8') if euro_sign.respond_to?(:force_encoding) | |
|
181 | euro_sign = "\xe2\x82\xac".force_encoding('UTF-8') | |
|
180 | 182 | assert_equal "-1000,20 #{euro_sign}", number_to_currency(-1000.2) |
|
181 | 183 | end |
|
182 | 184 | |
@@ -193,8 +195,7 class Redmine::I18nTest < ActiveSupport::TestCase | |||
|
193 | 195 | assert_nil options.detect {|option| option.size != 2} |
|
194 | 196 | assert_nil options.detect {|option| !option.first.is_a?(String) || !option.last.is_a?(String)} |
|
195 | 197 | assert_include ["English", "en"], options |
|
196 | ja = "Japanese (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)" | |
|
197 | ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding) | |
|
198 | ja = "Japanese (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)".force_encoding('UTF-8') | |
|
198 | 199 | assert_include [ja, "ja"], options |
|
199 | 200 | end |
|
200 | 201 | |
@@ -238,30 +239,21 class Redmine::I18nTest < ActiveSupport::TestCase | |||
|
238 | 239 | |
|
239 | 240 | def test_utf8 |
|
240 | 241 | set_language_if_valid 'ja' |
|
241 | str_ja_yes = "\xe3\x81\xaf\xe3\x81\x84" | |
|
242 | str_ja_yes = "\xe3\x81\xaf\xe3\x81\x84".force_encoding('UTF-8') | |
|
242 | 243 | i18n_ja_yes = l(:general_text_Yes) |
|
243 | if str_ja_yes.respond_to?(:force_encoding) | |
|
244 | str_ja_yes.force_encoding('UTF-8') | |
|
245 | assert_equal "UTF-8", i18n_ja_yes.encoding.to_s | |
|
246 | end | |
|
247 | 244 | assert_equal str_ja_yes, i18n_ja_yes |
|
245 | assert_equal "UTF-8", i18n_ja_yes.encoding.to_s | |
|
248 | 246 | end |
|
249 | 247 | |
|
250 | 248 | def test_traditional_chinese_locale |
|
251 | 249 | set_language_if_valid 'zh-TW' |
|
252 | str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)" | |
|
253 | if str_tw.respond_to?(:force_encoding) | |
|
254 | str_tw.force_encoding('UTF-8') | |
|
255 | end | |
|
250 | str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)".force_encoding('UTF-8') | |
|
256 | 251 | assert_equal str_tw, l(:general_lang_name) |
|
257 | 252 | end |
|
258 | 253 | |
|
259 | 254 | def test_french_locale |
|
260 | 255 | set_language_if_valid 'fr' |
|
261 | str_fr = "Fran\xc3\xa7ais" | |
|
262 | if str_fr.respond_to?(:force_encoding) | |
|
263 | str_fr.force_encoding('UTF-8') | |
|
264 | end | |
|
256 | str_fr = "Fran\xc3\xa7ais".force_encoding('UTF-8') | |
|
265 | 257 | assert_equal str_fr, l(:general_lang_name) |
|
266 | 258 | end |
|
267 | 259 | end |
@@ -16,210 +16,203 | |||
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../../../../test_helper', __FILE__) |
|
19 | begin | |
|
20 | require 'mocha/setup' | |
|
21 | ||
|
22 | class BazaarAdapterTest < ActiveSupport::TestCase | |
|
23 | REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s | |
|
24 | REPOSITORY_PATH.gsub!(/\/+/, '/') | |
|
25 | ||
|
26 | if File.directory?(REPOSITORY_PATH) | |
|
27 | def setup | |
|
28 | @adapter = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
29 | File.join(REPOSITORY_PATH, "trunk") | |
|
30 | ) | |
|
31 | end | |
|
32 | 19 | |
|
33 | def test_scm_version | |
|
34 | to_test = { "Bazaar (bzr) 2.1.2\n" => [2,1,2], | |
|
35 | "2.1.1\n1.7\n1.8" => [2,1,1], | |
|
36 | "2.0.1\r\n1.8.1\r\n1.9.1" => [2,0,1]} | |
|
37 | to_test.each do |s, v| | |
|
38 | test_scm_version_for(s, v) | |
|
39 | end | |
|
40 | end | |
|
20 | class BazaarAdapterTest < ActiveSupport::TestCase | |
|
21 | REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s | |
|
22 | REPOSITORY_PATH.gsub!(/\/+/, '/') | |
|
41 | 23 | |
|
42 | def test_cat | |
|
43 | cat = @adapter.cat('directory/document.txt') | |
|
44 | assert cat =~ /Write the contents of a file as of a given revision to standard output/ | |
|
45 | end | |
|
24 | if File.directory?(REPOSITORY_PATH) | |
|
25 | def setup | |
|
26 | @adapter = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
27 | File.join(REPOSITORY_PATH, "trunk") | |
|
28 | ) | |
|
29 | end | |
|
46 | 30 | |
|
47 |
|
|
|
48 | assert_nil @adapter.cat('invalid') | |
|
31 | def test_scm_version | |
|
32 | to_test = { "Bazaar (bzr) 2.1.2\n" => [2,1,2], | |
|
33 | "2.1.1\n1.7\n1.8" => [2,1,1], | |
|
34 | "2.0.1\r\n1.8.1\r\n1.9.1" => [2,0,1]} | |
|
35 | to_test.each do |s, v| | |
|
36 | test_scm_version_for(s, v) | |
|
49 | 37 | end |
|
38 | end | |
|
50 | 39 | |
|
51 |
|
|
|
52 | assert_nil @adapter.cat('doc-mkdir.txt', '12345678') | |
|
53 | end | |
|
40 | def test_cat | |
|
41 | cat = @adapter.cat('directory/document.txt') | |
|
42 | assert cat =~ /Write the contents of a file as of a given revision to standard output/ | |
|
43 | end | |
|
54 | 44 | |
|
55 | def test_diff | |
|
56 | diff1 = @adapter.diff('doc-mkdir.txt', 3, 2) | |
|
57 | assert_equal 21, diff1.size | |
|
58 | buf = diff1[14].gsub(/\r\n|\r|\n/, "") | |
|
59 | assert_equal "-Display more information.", buf | |
|
60 | end | |
|
45 | def test_cat_path_invalid | |
|
46 | assert_nil @adapter.cat('invalid') | |
|
47 | end | |
|
61 | 48 | |
|
62 |
|
|
|
63 | assert_equal [], @adapter.diff('invalid', 1) | |
|
64 |
|
|
|
49 | def test_cat_revision_invalid | |
|
50 | assert_nil @adapter.cat('doc-mkdir.txt', '12345678') | |
|
51 | end | |
|
65 | 52 | |
|
66 |
|
|
|
67 | assert_equal [], @adapter.diff(nil, 12345678) | |
|
68 | assert_equal [], @adapter.diff(nil, 12345678, 87654321) | |
|
69 | end | |
|
53 | def test_diff | |
|
54 | diff1 = @adapter.diff('doc-mkdir.txt', 3, 2) | |
|
55 | assert_equal 21, diff1.size | |
|
56 | buf = diff1[14].gsub(/\r\n|\r|\n/, "") | |
|
57 | assert_equal "-Display more information.", buf | |
|
58 | end | |
|
70 | 59 | |
|
71 | def test_annotate | |
|
72 | annotate = @adapter.annotate('doc-mkdir.txt') | |
|
73 | assert_equal 17, annotate.lines.size | |
|
74 | assert_equal '1', annotate.revisions[0].identifier | |
|
75 | assert_equal 'jsmith@', annotate.revisions[0].author | |
|
76 | assert_equal 'mkdir', annotate.lines[0] | |
|
77 | end | |
|
60 | def test_diff_path_invalid | |
|
61 | assert_equal [], @adapter.diff('invalid', 1) | |
|
62 | end | |
|
78 | 63 | |
|
79 |
|
|
|
80 | assert_nil @adapter.annotate('invalid') | |
|
81 | end | |
|
64 | def test_diff_revision_invalid | |
|
65 | assert_equal [], @adapter.diff(nil, 12345678) | |
|
66 | assert_equal [], @adapter.diff(nil, 12345678, 87654321) | |
|
67 | end | |
|
82 | 68 | |
|
83 |
|
|
|
84 |
|
|
|
85 | end | |
|
69 | def test_annotate | |
|
70 | annotate = @adapter.annotate('doc-mkdir.txt') | |
|
71 | assert_equal 17, annotate.lines.size | |
|
72 | assert_equal '1', annotate.revisions[0].identifier | |
|
73 | assert_equal 'jsmith@', annotate.revisions[0].author | |
|
74 | assert_equal 'mkdir', annotate.lines[0] | |
|
75 | end | |
|
86 | 76 | |
|
87 |
|
|
|
88 | p = "c:\\test\\test\\" | |
|
89 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
90 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
91 | p = "c:\\test\\test\\.bzr" | |
|
92 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
93 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
94 | p = "c:\\test\\test\\.bzr\\" | |
|
95 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
96 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
97 | p = "c:\\test\\test" | |
|
98 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
99 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
100 | p = "\\\\server\\test\\test\\" | |
|
101 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
102 | assert_equal File.join("\\\\server\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
103 | end | |
|
77 | def test_annotate_path_invalid | |
|
78 | assert_nil @adapter.annotate('invalid') | |
|
79 | end | |
|
104 | 80 | |
|
105 |
|
|
|
106 | assert_equal true, @adapter.append_revisions_only | |
|
107 |
|
|
|
81 | def test_annotate_revision_invalid | |
|
82 | assert_nil @adapter.annotate('doc-mkdir.txt', '12345678') | |
|
83 | end | |
|
108 | 84 | |
|
109 | def test_append_revisions_only_false | |
|
110 | adpt = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
111 | File.join(REPOSITORY_PATH, "empty-branch") | |
|
112 | ) | |
|
113 | assert_equal false, adpt.append_revisions_only | |
|
114 | end | |
|
85 | def test_branch_conf_path | |
|
86 | p = "c:\\test\\test\\" | |
|
87 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
88 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
89 | p = "c:\\test\\test\\.bzr" | |
|
90 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
91 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
92 | p = "c:\\test\\test\\.bzr\\" | |
|
93 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
94 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
95 | p = "c:\\test\\test" | |
|
96 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
97 | assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
98 | p = "\\\\server\\test\\test\\" | |
|
99 | bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p) | |
|
100 | assert_equal File.join("\\\\server\\test\\test", ".bzr", "branch", "branch.conf"), bcp | |
|
101 | end | |
|
115 | 102 | |
|
116 |
|
|
|
117 | adpt = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
118 | REPOSITORY_PATH | |
|
119 | ) | |
|
120 | assert_equal false, adpt.append_revisions_only | |
|
121 | end | |
|
103 | def test_append_revisions_only_true | |
|
104 | assert_equal true, @adapter.append_revisions_only | |
|
105 | end | |
|
122 | 106 | |
|
123 | def test_info_not_nil | |
|
124 | assert_not_nil @adapter.info | |
|
125 | end | |
|
107 | def test_append_revisions_only_false | |
|
108 | adpt = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
109 | File.join(REPOSITORY_PATH, "empty-branch") | |
|
110 | ) | |
|
111 | assert_equal false, adpt.append_revisions_only | |
|
112 | end | |
|
126 | 113 | |
|
127 | def test_info_nil | |
|
128 |
|
|
|
129 | "/invalid/invalid/" | |
|
130 | ) | |
|
131 | assert_nil adpt.info | |
|
132 |
|
|
|
114 | def test_append_revisions_only_shared_repo | |
|
115 | adpt = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
116 | REPOSITORY_PATH | |
|
117 | ) | |
|
118 | assert_equal false, adpt.append_revisions_only | |
|
119 | end | |
|
133 | 120 | |
|
134 |
|
|
|
135 |
|
|
|
136 | assert_equal 4, info.lastrev.identifier.to_i | |
|
137 | end | |
|
121 | def test_info_not_nil | |
|
122 | assert_not_nil @adapter.info | |
|
123 | end | |
|
138 | 124 | |
|
139 |
|
|
|
140 |
|
|
|
141 | File.join(REPOSITORY_PATH, "empty-branch") | |
|
142 |
|
|
|
143 | assert_equal 0, adpt.info.lastrev.identifier.to_i | |
|
144 |
|
|
|
125 | def test_info_nil | |
|
126 | adpt = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
127 | "/invalid/invalid/" | |
|
128 | ) | |
|
129 | assert_nil adpt.info | |
|
130 | end | |
|
145 | 131 | |
|
146 | def test_entries_path_invalid | |
|
147 | assert_equal [], @adapter.entries('invalid') | |
|
148 | end | |
|
132 | def test_info | |
|
133 | info = @adapter.info | |
|
134 | assert_equal 4, info.lastrev.identifier.to_i | |
|
135 | end | |
|
149 | 136 | |
|
150 | def test_entries_revision_invalid | |
|
151 | assert_nil @adapter.entries(nil, 12345678) | |
|
152 | end | |
|
137 | def test_info_emtpy | |
|
138 | adpt = Redmine::Scm::Adapters::BazaarAdapter.new( | |
|
139 | File.join(REPOSITORY_PATH, "empty-branch") | |
|
140 | ) | |
|
141 | assert_equal 0, adpt.info.lastrev.identifier.to_i | |
|
142 | end | |
|
153 | 143 | |
|
154 | def test_revisions | |
|
155 | revisions = @adapter.revisions(nil, 4, 2) | |
|
156 | assert_equal 3, revisions.size | |
|
157 | assert_equal 2, revisions[2].identifier | |
|
158 | assert_equal 'jsmith@foo.bar-20071203175224-v0eog5d5wrgdrshg', revisions[2].scmid | |
|
159 | assert_equal 4, revisions[0].identifier | |
|
160 | assert_equal 'jsmith@foo.bar-20071203175422-t40bf8li5zz0c4cg', revisions[0].scmid | |
|
161 | assert_equal 2, revisions[0].paths.size | |
|
162 | assert_equal 'D', revisions[0].paths[0][:action] | |
|
163 | assert_equal '/doc-deleted.txt', revisions[0].paths[0][:path] | |
|
164 | assert_equal 'docdeleted.txt-20071203175320-iwwj561ojuubs3gt-1', revisions[0].paths[0][:revision] | |
|
165 | assert_equal 'M', revisions[0].paths[1][:action] | |
|
166 | assert_equal '/directory/doc-ls.txt', revisions[0].paths[1][:path] | |
|
167 | assert_equal 'docls.txt-20071203175005-a3hyc3mn0shl7cgu-1', revisions[0].paths[1][:revision] | |
|
168 | end | |
|
144 | def test_entries_path_invalid | |
|
145 | assert_equal [], @adapter.entries('invalid') | |
|
146 | end | |
|
169 | 147 | |
|
170 |
|
|
|
171 |
|
|
|
172 |
|
|
|
148 | def test_entries_revision_invalid | |
|
149 | assert_nil @adapter.entries(nil, 12345678) | |
|
150 | end | |
|
173 | 151 | |
|
174 |
|
|
|
175 |
|
|
|
176 | assert_nil @adapter.revisions(nil, 12345678, 87654321) | |
|
177 | end | |
|
152 | def test_revisions | |
|
153 | revisions = @adapter.revisions(nil, 4, 2) | |
|
154 | assert_equal 3, revisions.size | |
|
155 | assert_equal 2, revisions[2].identifier | |
|
156 | assert_equal 'jsmith@foo.bar-20071203175224-v0eog5d5wrgdrshg', revisions[2].scmid | |
|
157 | assert_equal 4, revisions[0].identifier | |
|
158 | assert_equal 'jsmith@foo.bar-20071203175422-t40bf8li5zz0c4cg', revisions[0].scmid | |
|
159 | assert_equal 2, revisions[0].paths.size | |
|
160 | assert_equal 'D', revisions[0].paths[0][:action] | |
|
161 | assert_equal '/doc-deleted.txt', revisions[0].paths[0][:path] | |
|
162 | assert_equal 'docdeleted.txt-20071203175320-iwwj561ojuubs3gt-1', revisions[0].paths[0][:revision] | |
|
163 | assert_equal 'M', revisions[0].paths[1][:action] | |
|
164 | assert_equal '/directory/doc-ls.txt', revisions[0].paths[1][:path] | |
|
165 | assert_equal 'docls.txt-20071203175005-a3hyc3mn0shl7cgu-1', revisions[0].paths[1][:revision] | |
|
166 | end | |
|
178 | 167 | |
|
179 | def test_entry | |
|
180 | entry = @adapter.entry() | |
|
181 | assert_equal "", entry.path | |
|
182 | assert_equal "dir", entry.kind | |
|
183 | entry = @adapter.entry('') | |
|
184 | assert_equal "", entry.path | |
|
168 | def test_revisions_path_invalid | |
|
169 | assert_nil @adapter.revisions('invalid') | |
|
170 | end | |
|
171 | ||
|
172 | def test_revisions_revision_invalid | |
|
173 | assert_nil @adapter.revisions(nil, 12345678) | |
|
174 | assert_nil @adapter.revisions(nil, 12345678, 87654321) | |
|
175 | end | |
|
176 | ||
|
177 | def test_entry | |
|
178 | entry = @adapter.entry() | |
|
179 | assert_equal "", entry.path | |
|
180 | assert_equal "dir", entry.kind | |
|
181 | entry = @adapter.entry('') | |
|
182 | assert_equal "", entry.path | |
|
183 | assert_equal "dir", entry.kind | |
|
184 | assert_nil @adapter.entry('invalid') | |
|
185 | assert_nil @adapter.entry('/invalid') | |
|
186 | assert_nil @adapter.entry('/invalid/') | |
|
187 | assert_nil @adapter.entry('invalid/invalid') | |
|
188 | assert_nil @adapter.entry('invalid/invalid/') | |
|
189 | assert_nil @adapter.entry('/invalid/invalid') | |
|
190 | assert_nil @adapter.entry('/invalid/invalid/') | |
|
191 | ["doc-ls.txt", "/doc-ls.txt"].each do |path| | |
|
192 | entry = @adapter.entry(path, 2) | |
|
193 | assert_equal "doc-ls.txt", entry.path | |
|
194 | assert_equal "file", entry.kind | |
|
195 | end | |
|
196 | ["directory", "/directory", "/directory/"].each do |path| | |
|
197 | entry = @adapter.entry(path, 2) | |
|
198 | assert_equal "directory", entry.path | |
|
185 | 199 | assert_equal "dir", entry.kind |
|
186 | assert_nil @adapter.entry('invalid') | |
|
187 | assert_nil @adapter.entry('/invalid') | |
|
188 | assert_nil @adapter.entry('/invalid/') | |
|
189 | assert_nil @adapter.entry('invalid/invalid') | |
|
190 | assert_nil @adapter.entry('invalid/invalid/') | |
|
191 | assert_nil @adapter.entry('/invalid/invalid') | |
|
192 | assert_nil @adapter.entry('/invalid/invalid/') | |
|
193 | ["doc-ls.txt", "/doc-ls.txt"].each do |path| | |
|
194 | entry = @adapter.entry(path, 2) | |
|
195 | assert_equal "doc-ls.txt", entry.path | |
|
196 | assert_equal "file", entry.kind | |
|
197 | end | |
|
198 | ["directory", "/directory", "/directory/"].each do |path| | |
|
199 | entry = @adapter.entry(path, 2) | |
|
200 | assert_equal "directory", entry.path | |
|
201 | assert_equal "dir", entry.kind | |
|
202 | end | |
|
203 | ["directory/document.txt", "/directory/document.txt"].each do |path| | |
|
204 | entry = @adapter.entry(path, 2) | |
|
205 | assert_equal "directory/document.txt", entry.path | |
|
206 | assert_equal "file", entry.kind | |
|
207 | end | |
|
208 | 200 | end |
|
201 | ["directory/document.txt", "/directory/document.txt"].each do |path| | |
|
202 | entry = @adapter.entry(path, 2) | |
|
203 | assert_equal "directory/document.txt", entry.path | |
|
204 | assert_equal "file", entry.kind | |
|
205 | end | |
|
206 | end | |
|
209 | 207 | |
|
210 |
|
|
|
208 | private | |
|
211 | 209 | |
|
212 |
|
|
|
213 |
|
|
|
214 |
|
|
|
215 | end | |
|
216 | else | |
|
217 | puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!" | |
|
218 | def test_fake; assert true end | |
|
210 | def test_scm_version_for(scm_command_version, version) | |
|
211 | @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version) | |
|
212 | assert_equal version, @adapter.class.scm_command_version | |
|
219 | 213 | end |
|
220 | end | |
|
221 | rescue LoadError | |
|
222 | class BazaarMochaFake < ActiveSupport::TestCase | |
|
223 | def test_fake; assert(false, "Requires mocha to run those tests") end | |
|
214 | else | |
|
215 | puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!" | |
|
216 | def test_fake; assert true end | |
|
224 | 217 | end |
|
225 | 218 | end |
@@ -16,100 +16,91 | |||
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../../../../test_helper', __FILE__) |
|
19 | begin | |
|
20 | require 'mocha/setup' | |
|
21 | 19 | |
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
25 |
|
|
|
20 | class CvsAdapterTest < ActiveSupport::TestCase | |
|
21 | REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s | |
|
22 | REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin? | |
|
23 | MODULE_NAME = 'test' | |
|
26 | 24 | |
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
|
25 | if File.directory?(REPOSITORY_PATH) | |
|
26 | def setup | |
|
27 | @adapter = Redmine::Scm::Adapters::CvsAdapter.new(MODULE_NAME, REPOSITORY_PATH) | |
|
28 | end | |
|
31 | 29 | |
|
32 |
|
|
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
|
37 |
|
|
|
38 | end | |
|
30 | def test_scm_version | |
|
31 | to_test = { "\nConcurrent Versions System (CVS) 1.12.13 (client/server)\n" => [1,12,13], | |
|
32 | "\r\n1.12.12\r\n1.12.11" => [1,12,12], | |
|
33 | "1.12.11\r\n1.12.10\r\n" => [1,12,11]} | |
|
34 | to_test.each do |s, v| | |
|
35 | test_scm_version_for(s, v) | |
|
39 | 36 | end |
|
37 | end | |
|
40 | 38 | |
|
41 |
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
|
45 | end | |
|
46 | assert_equal 16, cnt | |
|
39 | def test_revisions_all | |
|
40 | cnt = 0 | |
|
41 | @adapter.revisions('', nil, nil, :log_encoding => 'UTF-8') do |revision| | |
|
42 | cnt += 1 | |
|
47 | 43 | end |
|
44 | assert_equal 16, cnt | |
|
45 | end | |
|
48 | 46 | |
|
49 |
|
|
|
50 |
|
|
|
51 |
|
|
|
52 |
|
|
|
53 |
|
|
|
54 | end | |
|
55 | assert_equal 4, cnt | |
|
47 | def test_revisions_from_rev3 | |
|
48 | rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22) | |
|
49 | cnt = 0 | |
|
50 | @adapter.revisions('', rev3_committed_on, nil, :log_encoding => 'UTF-8') do |revision| | |
|
51 | cnt += 1 | |
|
56 | 52 | end |
|
53 | assert_equal 4, cnt | |
|
54 | end | |
|
57 | 55 | |
|
58 |
|
|
|
59 |
|
|
|
60 |
|
|
|
61 |
|
|
|
62 |
|
|
|
63 |
|
|
|
64 |
|
|
|
56 | def test_entries_rev3 | |
|
57 | rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22) | |
|
58 | entries = @adapter.entries('sources', rev3_committed_on) | |
|
59 | assert_equal 2, entries.size | |
|
60 | assert_equal entries[0].name, "watchers_controller.rb" | |
|
61 | assert_equal entries[0].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22) | |
|
62 | end | |
|
65 | 63 | |
|
66 |
|
|
|
67 |
|
|
|
68 |
|
|
|
69 |
|
|
|
70 |
|
|
|
71 |
|
|
|
72 |
|
|
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
|
76 |
|
|
|
77 |
|
|
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
|
64 | def test_path_encoding_default_utf8 | |
|
65 | adpt1 = Redmine::Scm::Adapters::CvsAdapter.new( | |
|
66 | MODULE_NAME, | |
|
67 | REPOSITORY_PATH | |
|
68 | ) | |
|
69 | assert_equal "UTF-8", adpt1.path_encoding | |
|
70 | adpt2 = Redmine::Scm::Adapters::CvsAdapter.new( | |
|
71 | MODULE_NAME, | |
|
72 | REPOSITORY_PATH, | |
|
73 | nil, | |
|
74 | nil, | |
|
75 | "" | |
|
76 | ) | |
|
77 | assert_equal "UTF-8", adpt2.path_encoding | |
|
78 | end | |
|
81 | 79 | |
|
82 |
|
|
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
|
86 |
|
|
|
87 |
|
|
|
88 |
|
|
|
89 |
|
|
|
90 |
|
|
|
91 |
|
|
|
80 | def test_root_url_path | |
|
81 | to_test = { | |
|
82 | ':pserver:cvs_user:cvs_password@123.456.789.123:9876/repo' => '/repo', | |
|
83 | ':pserver:cvs_user:cvs_password@123.456.789.123/repo' => '/repo', | |
|
84 | ':pserver:cvs_user:cvs_password@cvs_server:/repo' => '/repo', | |
|
85 | ':pserver:cvs_user:cvs_password@cvs_server:9876/repo' => '/repo', | |
|
86 | ':pserver:cvs_user:cvs_password@cvs_server/repo' => '/repo', | |
|
87 | ':pserver:cvs_user:cvs_password@cvs_server/path/repo' => '/path/repo', | |
|
88 | ':ext:cvsservername:/path' => '/path' | |
|
89 | } | |
|
92 | 90 | |
|
93 |
|
|
|
94 |
|
|
|
95 | end | |
|
91 | to_test.each do |string, expected| | |
|
92 | assert_equal expected, Redmine::Scm::Adapters::CvsAdapter.new('foo', string).send(:root_url_path), "#{string} failed" | |
|
96 | 93 | end |
|
94 | end | |
|
97 | 95 | |
|
98 |
|
|
|
96 | private | |
|
99 | 97 | |
|
100 |
|
|
|
101 |
|
|
|
102 |
|
|
|
103 | end | |
|
104 | else | |
|
105 | puts "Cvs test repository NOT FOUND. Skipping unit tests !!!" | |
|
106 | def test_fake; assert true end | |
|
98 | def test_scm_version_for(scm_command_version, version) | |
|
99 | @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version) | |
|
100 | assert_equal version, @adapter.class.scm_command_version | |
|
107 | 101 | end |
|
108 | end | |
|
109 | ||
|
110 | rescue LoadError | |
|
111 | class CvsMochaFake < ActiveSupport::TestCase | |
|
112 | def test_fake; assert(false, "Requires mocha to run those tests") end | |
|
102 | else | |
|
103 | puts "Cvs test repository NOT FOUND. Skipping unit tests !!!" | |
|
104 | def test_fake; assert true end | |
|
113 | 105 | end |
|
114 | 106 | end |
|
115 |
@@ -16,54 +16,45 | |||
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../../../../test_helper', __FILE__) |
|
19 | begin | |
|
20 | require 'mocha/setup' | |
|
21 | 19 | |
|
22 |
|
|
|
23 |
|
|
|
20 | class DarcsAdapterTest < ActiveSupport::TestCase | |
|
21 | REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s | |
|
24 | 22 | |
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
|
28 |
|
|
|
29 | ||
|
30 | def test_darcsversion | |
|
31 | to_test = { "1.0.9 (release)\n" => [1,0,9] , | |
|
32 | "2.2.0 (release)\n" => [2,2,0] } | |
|
33 | to_test.each do |s, v| | |
|
34 | test_darcsversion_for(s, v) | |
|
35 | end | |
|
36 | end | |
|
23 | if File.directory?(REPOSITORY_PATH) | |
|
24 | def setup | |
|
25 | @adapter = Redmine::Scm::Adapters::DarcsAdapter.new(REPOSITORY_PATH) | |
|
26 | end | |
|
37 | 27 | |
|
38 |
|
|
|
39 | id1 = '20080308225258-98289-761f654d669045eabee90b91b53a21ce5593cadf.gz' | |
|
40 | revs = @adapter.revisions('', nil, nil, {:with_path => true}) | |
|
41 | assert_equal 6, revs.size | |
|
42 | assert_equal id1, revs[5].scmid | |
|
43 | paths = revs[5].paths | |
|
44 | assert_equal 5, paths.size | |
|
45 | assert_equal 'A', paths[0][:action] | |
|
46 | assert_equal '/README', paths[0][:path] | |
|
47 | assert_equal 'A', paths[1][:action] | |
|
48 | assert_equal '/images', paths[1][:path] | |
|
28 | def test_darcsversion | |
|
29 | to_test = { "1.0.9 (release)\n" => [1,0,9] , | |
|
30 | "2.2.0 (release)\n" => [2,2,0] } | |
|
31 | to_test.each do |s, v| | |
|
32 | test_darcsversion_for(s, v) | |
|
49 | 33 | end |
|
34 | end | |
|
50 | 35 | |
|
51 | private | |
|
36 | def test_revisions | |
|
37 | id1 = '20080308225258-98289-761f654d669045eabee90b91b53a21ce5593cadf.gz' | |
|
38 | revs = @adapter.revisions('', nil, nil, {:with_path => true}) | |
|
39 | assert_equal 6, revs.size | |
|
40 | assert_equal id1, revs[5].scmid | |
|
41 | paths = revs[5].paths | |
|
42 | assert_equal 5, paths.size | |
|
43 | assert_equal 'A', paths[0][:action] | |
|
44 | assert_equal '/README', paths[0][:path] | |
|
45 | assert_equal 'A', paths[1][:action] | |
|
46 | assert_equal '/images', paths[1][:path] | |
|
47 | end | |
|
52 | 48 | |
|
53 | def test_darcsversion_for(darcsversion, version) | |
|
54 | @adapter.class.expects(:darcs_binary_version_from_command_line).returns(darcsversion) | |
|
55 | assert_equal version, @adapter.class.darcs_binary_version | |
|
56 | end | |
|
49 | private | |
|
57 | 50 | |
|
58 | else | |
|
59 | puts "Darcs test repository NOT FOUND. Skipping unit tests !!!" | |
|
60 | def test_fake; assert true end | |
|
51 | def test_darcsversion_for(darcsversion, version) | |
|
52 | @adapter.class.expects(:darcs_binary_version_from_command_line).returns(darcsversion) | |
|
53 | assert_equal version, @adapter.class.darcs_binary_version | |
|
61 | 54 | end |
|
62 | end | |
|
63 | 55 | |
|
64 | rescue LoadError | |
|
65 | class DarcsMochaFake < ActiveSupport::TestCase | |
|
66 |
def test_fake; assert |
|
|
56 | else | |
|
57 | puts "Darcs test repository NOT FOUND. Skipping unit tests !!!" | |
|
58 | def test_fake; assert true end | |
|
67 | 59 | end |
|
68 | 60 | end |
|
69 |
This diff has been collapsed as it changes many lines, (1028 lines changed) Show them Hide them | |||
@@ -16,594 +16,582 | |||
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../../../../../test_helper', __FILE__) |
|
19 | begin | |
|
20 | require 'mocha/setup' | |
|
21 | ||
|
22 | class GitAdapterTest < ActiveSupport::TestCase | |
|
23 | REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s | |
|
24 | ||
|
25 | FELIX_HEX = "Felix Sch\xC3\xA4fer" | |
|
26 | CHAR_1_HEX = "\xc3\x9c" | |
|
27 | ||
|
28 | ## Git, Mercurial and CVS path encodings are binary. | |
|
29 | ## Subversion supports URL encoding for path. | |
|
30 | ## Redmine Mercurial adapter and extension use URL encoding. | |
|
31 | ## Git accepts only binary path in command line parameter. | |
|
32 | ## So, there is no way to use binary command line parameter in JRuby. | |
|
33 | JRUBY_SKIP = (RUBY_PLATFORM == 'java') | |
|
34 | JRUBY_SKIP_STR = "TODO: This test fails in JRuby" | |
|
35 | ||
|
36 | if File.directory?(REPOSITORY_PATH) | |
|
37 | ## Ruby uses ANSI api to fork a process on Windows. | |
|
38 | ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem | |
|
39 | ## and these are incompatible with ASCII. | |
|
40 | ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10 | |
|
41 | ## http://code.google.com/p/msysgit/issues/detail?id=80 | |
|
42 | ## So, Latin-1 path tests fail on Japanese Windows | |
|
43 | WINDOWS_PASS = (Redmine::Platform.mswin? && | |
|
44 | Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10])) | |
|
45 | WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10" | |
|
46 | ||
|
47 | def setup | |
|
48 | adapter_class = Redmine::Scm::Adapters::GitAdapter | |
|
49 | assert adapter_class | |
|
50 | assert adapter_class.client_command | |
|
51 | assert_equal true, adapter_class.client_available | |
|
52 | assert_equal true, adapter_class.client_version_above?([1]) | |
|
53 | assert_equal true, adapter_class.client_version_above?([1, 0]) | |
|
54 | ||
|
55 | @adapter = Redmine::Scm::Adapters::GitAdapter.new( | |
|
56 | REPOSITORY_PATH, | |
|
57 | nil, | |
|
58 | nil, | |
|
59 | nil, | |
|
60 | 'ISO-8859-1' | |
|
61 | ) | |
|
62 | assert @adapter | |
|
63 | @char_1 = CHAR_1_HEX.dup | |
|
64 | @str_felix_hex = FELIX_HEX.dup | |
|
65 | if @char_1.respond_to?(:force_encoding) | |
|
66 | @char_1.force_encoding('UTF-8') | |
|
67 | @str_felix_hex.force_encoding('ASCII-8BIT') | |
|
68 | end | |
|
69 | end | |
|
70 | 19 | |
|
71 | def test_scm_version | |
|
72 | to_test = { "git version 1.7.3.4\n" => [1,7,3,4], | |
|
73 | "1.6.1\n1.7\n1.8" => [1,6,1], | |
|
74 | "1.6.2\r\n1.8.1\r\n1.9.1" => [1,6,2]} | |
|
75 | to_test.each do |s, v| | |
|
76 | test_scm_version_for(s, v) | |
|
77 | end | |
|
78 | end | |
|
20 | class GitAdapterTest < ActiveSupport::TestCase | |
|
21 | REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s | |
|
22 | ||
|
23 | FELIX_HEX = "Felix Sch\xC3\xA4fer" | |
|
24 | CHAR_1_HEX = "\xc3\x9c" | |
|
25 | ||
|
26 | ## Git, Mercurial and CVS path encodings are binary. | |
|
27 | ## Subversion supports URL encoding for path. | |
|
28 | ## Redmine Mercurial adapter and extension use URL encoding. | |
|
29 | ## Git accepts only binary path in command line parameter. | |
|
30 | ## So, there is no way to use binary command line parameter in JRuby. | |
|
31 | JRUBY_SKIP = (RUBY_PLATFORM == 'java') | |
|
32 | JRUBY_SKIP_STR = "TODO: This test fails in JRuby" | |
|
33 | ||
|
34 | if File.directory?(REPOSITORY_PATH) | |
|
35 | ## Ruby uses ANSI api to fork a process on Windows. | |
|
36 | ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem | |
|
37 | ## and these are incompatible with ASCII. | |
|
38 | ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10 | |
|
39 | ## http://code.google.com/p/msysgit/issues/detail?id=80 | |
|
40 | ## So, Latin-1 path tests fail on Japanese Windows | |
|
41 | WINDOWS_PASS = (Redmine::Platform.mswin? && | |
|
42 | Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10])) | |
|
43 | WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10" | |
|
44 | ||
|
45 | def setup | |
|
46 | adapter_class = Redmine::Scm::Adapters::GitAdapter | |
|
47 | assert adapter_class | |
|
48 | assert adapter_class.client_command | |
|
49 | assert_equal true, adapter_class.client_available | |
|
50 | assert_equal true, adapter_class.client_version_above?([1]) | |
|
51 | assert_equal true, adapter_class.client_version_above?([1, 0]) | |
|
52 | ||
|
53 | @adapter = Redmine::Scm::Adapters::GitAdapter.new( | |
|
54 | REPOSITORY_PATH, | |
|
55 | nil, | |
|
56 | nil, | |
|
57 | nil, | |
|
58 | 'ISO-8859-1' | |
|
59 | ) | |
|
60 | assert @adapter | |
|
61 | @char_1 = CHAR_1_HEX.dup.force_encoding('UTF-8') | |
|
62 | @str_felix_hex = FELIX_HEX.dup.force_encoding('ASCII-8BIT') | |
|
63 | end | |
|
79 | 64 | |
|
80 |
|
|
|
81 | brs = [] | |
|
82 | @adapter.branches.each do |b| | |
|
83 | brs << b | |
|
84 | end | |
|
85 | assert_equal 6, brs.length | |
|
86 | br_issue_8857 = brs[0] | |
|
87 | assert_equal 'issue-8857', br_issue_8857.to_s | |
|
88 | assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision | |
|
89 | assert_equal br_issue_8857.scmid, br_issue_8857.revision | |
|
90 | assert_equal false, br_issue_8857.is_default | |
|
91 | br_latin_1_path = brs[1] | |
|
92 | assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s | |
|
93 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision | |
|
94 | assert_equal br_latin_1_path.scmid, br_latin_1_path.revision | |
|
95 | assert_equal false, br_latin_1_path.is_default | |
|
96 | br_master = brs[2] | |
|
97 | assert_equal 'master', br_master.to_s | |
|
98 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision | |
|
99 | assert_equal br_master.scmid, br_master.revision | |
|
100 | assert_equal false, br_master.is_default | |
|
101 | br_master_20120212 = brs[3] | |
|
102 | assert_equal 'master-20120212', br_master_20120212.to_s | |
|
103 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision | |
|
104 | assert_equal br_master_20120212.scmid, br_master_20120212.revision | |
|
105 | assert_equal true, br_master_20120212.is_default | |
|
106 | br_latin_1 = brs[-2] | |
|
107 | assert_equal 'test-latin-1', br_latin_1.to_s | |
|
108 | assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision | |
|
109 | assert_equal br_latin_1.scmid, br_latin_1.revision | |
|
110 | assert_equal false, br_latin_1.is_default | |
|
111 | br_test = brs[-1] | |
|
112 | assert_equal 'test_branch', br_test.to_s | |
|
113 | assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision | |
|
114 | assert_equal br_test.scmid, br_test.revision | |
|
115 | assert_equal false, br_test.is_default | |
|
65 | def test_scm_version | |
|
66 | to_test = { "git version 1.7.3.4\n" => [1,7,3,4], | |
|
67 | "1.6.1\n1.7\n1.8" => [1,6,1], | |
|
68 | "1.6.2\r\n1.8.1\r\n1.9.1" => [1,6,2]} | |
|
69 | to_test.each do |s, v| | |
|
70 | test_scm_version_for(s, v) | |
|
116 | 71 | end |
|
72 | end | |
|
117 | 73 | |
|
118 |
|
|
|
119 | assert_equal 'master-20120212', @adapter.default_branch | |
|
120 | end | |
|
74 | def test_branches | |
|
75 | brs = [] | |
|
76 | @adapter.branches.each do |b| | |
|
77 | brs << b | |
|
78 | end | |
|
79 | assert_equal 6, brs.length | |
|
80 | br_issue_8857 = brs[0] | |
|
81 | assert_equal 'issue-8857', br_issue_8857.to_s | |
|
82 | assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision | |
|
83 | assert_equal br_issue_8857.scmid, br_issue_8857.revision | |
|
84 | assert_equal false, br_issue_8857.is_default | |
|
85 | br_latin_1_path = brs[1] | |
|
86 | assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s | |
|
87 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision | |
|
88 | assert_equal br_latin_1_path.scmid, br_latin_1_path.revision | |
|
89 | assert_equal false, br_latin_1_path.is_default | |
|
90 | br_master = brs[2] | |
|
91 | assert_equal 'master', br_master.to_s | |
|
92 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision | |
|
93 | assert_equal br_master.scmid, br_master.revision | |
|
94 | assert_equal false, br_master.is_default | |
|
95 | br_master_20120212 = brs[3] | |
|
96 | assert_equal 'master-20120212', br_master_20120212.to_s | |
|
97 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision | |
|
98 | assert_equal br_master_20120212.scmid, br_master_20120212.revision | |
|
99 | assert_equal true, br_master_20120212.is_default | |
|
100 | br_latin_1 = brs[-2] | |
|
101 | assert_equal 'test-latin-1', br_latin_1.to_s | |
|
102 | assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision | |
|
103 | assert_equal br_latin_1.scmid, br_latin_1.revision | |
|
104 | assert_equal false, br_latin_1.is_default | |
|
105 | br_test = brs[-1] | |
|
106 | assert_equal 'test_branch', br_test.to_s | |
|
107 | assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision | |
|
108 | assert_equal br_test.scmid, br_test.revision | |
|
109 | assert_equal false, br_test.is_default | |
|
110 | end | |
|
121 | 111 | |
|
122 |
|
|
|
123 | assert_equal [ | |
|
124 | "tag00.lightweight", | |
|
125 | "tag01.annotated", | |
|
126 | ], @adapter.tags | |
|
127 | end | |
|
112 | def test_default_branch | |
|
113 | assert_equal 'master-20120212', @adapter.default_branch | |
|
114 | end | |
|
128 | 115 | |
|
129 | def test_revisions_master_all | |
|
130 | revs1 = [] | |
|
131 | @adapter.revisions('', nil, "master",{}) do |rev| | |
|
132 | revs1 << rev | |
|
133 | end | |
|
134 | assert_equal 15, revs1.length | |
|
135 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier | |
|
136 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier | |
|
137 | ||
|
138 | revs2 = [] | |
|
139 | @adapter.revisions('', nil, "master", | |
|
140 | {:reverse => true}) do |rev| | |
|
141 | revs2 << rev | |
|
142 | end | |
|
143 | assert_equal 15, revs2.length | |
|
144 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier | |
|
145 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier | |
|
146 | end | |
|
116 | def test_tags | |
|
117 | assert_equal [ | |
|
118 | "tag00.lightweight", | |
|
119 | "tag01.annotated", | |
|
120 | ], @adapter.tags | |
|
121 | end | |
|
147 | 122 | |
|
148 |
|
|
|
149 |
|
|
|
150 |
|
|
|
151 | "713f4944648826f558cf548222f813dabe7cbb04", | |
|
152 | "master", | |
|
153 | {:reverse => true}) do |rev| | |
|
154 | revs1 << rev | |
|
155 | end | |
|
156 | assert_equal 8, revs1.length | |
|
157 | assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier | |
|
158 | assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier | |
|
159 | # 4a07fe31b is not a child of 713f49446 | |
|
160 | assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier | |
|
161 | # Merged revision | |
|
162 | assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier | |
|
163 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier | |
|
164 | ||
|
165 | revs2 = [] | |
|
166 | @adapter.revisions('', | |
|
167 | "fba357b886984ee71185ad2065e65fc0417d9b92", | |
|
168 | "master", | |
|
169 | {:reverse => true}) do |rev| | |
|
170 | revs2 << rev | |
|
171 | end | |
|
172 | assert_equal 7, revs2.length | |
|
173 | assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier | |
|
174 | # 4a07fe31b is not a child of fba357b8869 | |
|
175 | assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier | |
|
176 | # Merged revision | |
|
177 | assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier | |
|
178 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier | |
|
123 | def test_revisions_master_all | |
|
124 | revs1 = [] | |
|
125 | @adapter.revisions('', nil, "master",{}) do |rev| | |
|
126 | revs1 << rev | |
|
179 | 127 | end |
|
128 | assert_equal 15, revs1.length | |
|
129 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier | |
|
130 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier | |
|
180 | 131 | |
|
181 | def test_revisions_branch_latin_1_path_encoding_all | |
|
182 | revs1 = [] | |
|
183 | @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev| | |
|
184 |
|
|
|
185 | end | |
|
186 | assert_equal 8, revs1.length | |
|
187 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier | |
|
188 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier | |
|
189 | ||
|
190 | revs2 = [] | |
|
191 | @adapter.revisions('', nil, "latin-1-path-encoding", | |
|
192 | {:reverse => true}) do |rev| | |
|
193 | revs2 << rev | |
|
194 | end | |
|
195 | assert_equal 8, revs2.length | |
|
196 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier | |
|
197 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier | |
|
132 | revs2 = [] | |
|
133 | @adapter.revisions('', nil, "master", | |
|
134 | {:reverse => true}) do |rev| | |
|
135 | revs2 << rev | |
|
198 | 136 | end |
|
137 | assert_equal 15, revs2.length | |
|
138 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier | |
|
139 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier | |
|
140 | end | |
|
199 | 141 | |
|
200 |
|
|
|
201 |
|
|
|
202 |
|
|
|
203 | '7234cb2750b63f47bff735edc50a1c0a433c2518', | |
|
204 |
|
|
|
205 |
|
|
|
206 |
|
|
|
207 |
|
|
|
208 |
|
|
|
209 |
|
|
|
210 |
|
|
|
142 | def test_revisions_master_merged_rev | |
|
143 | revs1 = [] | |
|
144 | @adapter.revisions('', | |
|
145 | "713f4944648826f558cf548222f813dabe7cbb04", | |
|
146 | "master", | |
|
147 | {:reverse => true}) do |rev| | |
|
148 | revs1 << rev | |
|
149 | end | |
|
150 | assert_equal 8, revs1.length | |
|
151 | assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier | |
|
152 | assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier | |
|
153 | # 4a07fe31b is not a child of 713f49446 | |
|
154 | assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier | |
|
155 | # Merged revision | |
|
156 | assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier | |
|
157 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier | |
|
158 | ||
|
159 | revs2 = [] | |
|
160 | @adapter.revisions('', | |
|
161 | "fba357b886984ee71185ad2065e65fc0417d9b92", | |
|
162 | "master", | |
|
163 | {:reverse => true}) do |rev| | |
|
164 | revs2 << rev | |
|
165 | end | |
|
166 | assert_equal 7, revs2.length | |
|
167 | assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier | |
|
168 | # 4a07fe31b is not a child of fba357b8869 | |
|
169 | assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier | |
|
170 | # Merged revision | |
|
171 | assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier | |
|
172 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier | |
|
173 | end | |
|
211 | 174 | |
|
212 | revs2 = [] | |
|
213 | @adapter.revisions('', | |
|
214 | '57ca437c0acbbcb749821fdf3726a1367056d364', | |
|
215 | "latin-1-path-encoding", | |
|
216 | {:reverse => true}) do |rev| | |
|
217 | revs2 << rev | |
|
218 | end | |
|
219 | assert_equal 3, revs2.length | |
|
220 | assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier | |
|
221 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier | |
|
175 | def test_revisions_branch_latin_1_path_encoding_all | |
|
176 | revs1 = [] | |
|
177 | @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev| | |
|
178 | revs1 << rev | |
|
222 | 179 | end |
|
180 | assert_equal 8, revs1.length | |
|
181 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier | |
|
182 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier | |
|
223 | 183 | |
|
224 | def test_revisions_invalid_rev | |
|
225 | assert_equal [], @adapter.revisions('', '1234abcd', "master") | |
|
226 | assert_raise Redmine::Scm::Adapters::CommandFailed do | |
|
227 |
|
|
|
228 | @adapter.revisions('', | |
|
229 | '1234abcd', | |
|
230 | "master", | |
|
231 | {:reverse => true}) do |rev| | |
|
232 | revs1 << rev | |
|
233 | end | |
|
234 | end | |
|
184 | revs2 = [] | |
|
185 | @adapter.revisions('', nil, "latin-1-path-encoding", | |
|
186 | {:reverse => true}) do |rev| | |
|
187 | revs2 << rev | |
|
235 | 188 | end |
|
189 | assert_equal 8, revs2.length | |
|
190 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier | |
|
191 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier | |
|
192 | end | |
|
236 | 193 | |
|
237 |
|
|
|
238 |
|
|
|
239 |
|
|
|
240 | {:reverse => true, | |
|
241 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], | |
|
242 | :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev| | |
|
243 |
|
|
|
244 |
|
|
|
245 |
|
|
|
246 | assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier | |
|
247 |
|
|
|
248 | end | |
|
194 | def test_revisions_branch_latin_1_path_encoding_with_rev | |
|
195 | revs1 = [] | |
|
196 | @adapter.revisions('', | |
|
197 | '7234cb2750b63f47bff735edc50a1c0a433c2518', | |
|
198 | "latin-1-path-encoding", | |
|
199 | {:reverse => true}) do |rev| | |
|
200 | revs1 << rev | |
|
201 | end | |
|
202 | assert_equal 7, revs1.length | |
|
203 | assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier | |
|
204 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier | |
|
205 | ||
|
206 | revs2 = [] | |
|
207 | @adapter.revisions('', | |
|
208 | '57ca437c0acbbcb749821fdf3726a1367056d364', | |
|
209 | "latin-1-path-encoding", | |
|
210 | {:reverse => true}) do |rev| | |
|
211 | revs2 << rev | |
|
212 | end | |
|
213 | assert_equal 3, revs2.length | |
|
214 | assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier | |
|
215 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier | |
|
216 | end | |
|
249 | 217 | |
|
250 |
|
|
|
218 | def test_revisions_invalid_rev | |
|
219 | assert_equal [], @adapter.revisions('', '1234abcd', "master") | |
|
220 | assert_raise Redmine::Scm::Adapters::CommandFailed do | |
|
251 | 221 | revs1 = [] |
|
252 |
@adapter.revisions('', |
|
|
253 |
|
|
|
254 | :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'], | |
|
255 |
|
|
|
222 | @adapter.revisions('', | |
|
223 | '1234abcd', | |
|
224 | "master", | |
|
225 | {:reverse => true}) do |rev| | |
|
256 | 226 | revs1 << rev |
|
257 | 227 | end |
|
258 | assert_equal 2, revs1.length | |
|
259 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier | |
|
260 | assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier | |
|
261 | 228 | end |
|
229 | end | |
|
262 | 230 | |
|
263 |
|
|
|
264 |
|
|
|
265 |
|
|
|
266 |
|
|
|
267 |
|
|
|
268 |
|
|
|
269 |
|
|
|
270 |
|
|
|
271 |
|
|
|
272 |
|
|
|
273 | assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier | |
|
274 | assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier | |
|
275 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier | |
|
276 | end | |
|
231 | def test_revisions_includes_master_two_revs | |
|
232 | revs1 = [] | |
|
233 | @adapter.revisions('', nil, nil, | |
|
234 | {:reverse => true, | |
|
235 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], | |
|
236 | :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev| | |
|
237 | revs1 << rev | |
|
238 | end | |
|
239 | assert_equal 2, revs1.length | |
|
240 | assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier | |
|
241 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier | |
|
242 | end | |
|
277 | 243 | |
|
278 |
|
|
|
279 |
|
|
|
280 |
|
|
|
281 |
|
|
|
282 |
|
|
|
283 | '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'], | |
|
284 | :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43', | |
|
285 | '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev| | |
|
286 | revs1 << rev | |
|
287 | end | |
|
288 | assert_equal 4, revs1.length | |
|
289 | assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier | |
|
290 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier | |
|
291 | assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier | |
|
292 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier | |
|
293 | end | |
|
244 | def test_revisions_includes_master_two_revs_from_origin | |
|
245 | revs1 = [] | |
|
246 | @adapter.revisions('', nil, nil, | |
|
247 | {:reverse => true, | |
|
248 | :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'], | |
|
249 | :excludes => []}) do |rev| | |
|
250 | revs1 << rev | |
|
251 | end | |
|
252 | assert_equal 2, revs1.length | |
|
253 | assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier | |
|
254 | assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier | |
|
255 | end | |
|
294 | 256 | |
|
295 |
|
|
|
257 | def test_revisions_includes_merged_revs | |
|
258 | revs1 = [] | |
|
259 | @adapter.revisions('', nil, nil, | |
|
260 | {:reverse => true, | |
|
261 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], | |
|
262 | :excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev| | |
|
263 | revs1 << rev | |
|
264 | end | |
|
265 | assert_equal 7, revs1.length | |
|
266 | assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier | |
|
267 | assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier | |
|
268 | assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier | |
|
269 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier | |
|
270 | end | |
|
271 | ||
|
272 | def test_revisions_includes_two_heads | |
|
273 | revs1 = [] | |
|
274 | @adapter.revisions('', nil, nil, | |
|
275 | {:reverse => true, | |
|
276 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', | |
|
277 | '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'], | |
|
278 | :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43', | |
|
279 | '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev| | |
|
280 | revs1 << rev | |
|
281 | end | |
|
282 | assert_equal 4, revs1.length | |
|
283 | assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier | |
|
284 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier | |
|
285 | assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier | |
|
286 | assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier | |
|
287 | end | |
|
288 | ||
|
289 | def test_revisions_disjointed_histories_revisions | |
|
290 | revs1 = [] | |
|
291 | @adapter.revisions('', nil, nil, | |
|
292 | {:reverse => true, | |
|
293 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', | |
|
294 | '92397af84d22f27389c822848ecd5b463c181583'], | |
|
295 | :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63', | |
|
296 | '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev| | |
|
297 | revs1 << rev | |
|
298 | end | |
|
299 | assert_equal 4, revs1.length | |
|
300 | assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier | |
|
301 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier | |
|
302 | assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier | |
|
303 | assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier | |
|
304 | end | |
|
305 | ||
|
306 | def test_revisions_invalid_rev_excludes | |
|
307 | assert_equal [], | |
|
308 | @adapter.revisions('', nil, nil, | |
|
309 | {:reverse => true, | |
|
310 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], | |
|
311 | :excludes => ['0123abcd4567']}) | |
|
312 | assert_raise Redmine::Scm::Adapters::CommandFailed do | |
|
296 | 313 | revs1 = [] |
|
297 | 314 | @adapter.revisions('', nil, nil, |
|
298 | 315 | {:reverse => true, |
|
299 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', | |
|
300 | '92397af84d22f27389c822848ecd5b463c181583'], | |
|
301 | :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63', | |
|
302 | '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev| | |
|
316 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], | |
|
317 | :excludes => ['0123abcd4567']}) do |rev| | |
|
303 | 318 | revs1 << rev |
|
304 | 319 | end |
|
305 | assert_equal 4, revs1.length | |
|
306 | assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier | |
|
307 | assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier | |
|
308 | assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier | |
|
309 | assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier | |
|
310 | end | |
|
311 | ||
|
312 | def test_revisions_invalid_rev_excludes | |
|
313 | assert_equal [], | |
|
314 | @adapter.revisions('', nil, nil, | |
|
315 | {:reverse => true, | |
|
316 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], | |
|
317 | :excludes => ['0123abcd4567']}) | |
|
318 | assert_raise Redmine::Scm::Adapters::CommandFailed do | |
|
319 | revs1 = [] | |
|
320 | @adapter.revisions('', nil, nil, | |
|
321 | {:reverse => true, | |
|
322 | :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'], | |
|
323 | :excludes => ['0123abcd4567']}) do |rev| | |
|
324 | revs1 << rev | |
|
325 | end | |
|
326 | end | |
|
327 | 320 | end |
|
321 | end | |
|
328 | 322 | |
|
329 |
|
|
|
330 |
|
|
|
331 |
|
|
|
332 |
|
|
|
323 | def test_getting_revisions_with_spaces_in_filename | |
|
324 | assert_equal 1, @adapter.revisions("filemane with spaces.txt", | |
|
325 | nil, "master").length | |
|
326 | end | |
|
333 | 327 | |
|
334 |
|
|
|
335 |
|
|
|
336 |
|
|
|
337 |
|
|
|
338 |
|
|
|
339 |
|
|
|
340 |
|
|
|
341 |
|
|
|
342 |
|
|
|
343 |
|
|
|
344 |
|
|
|
345 |
|
|
|
346 |
|
|
|
347 |
|
|
|
348 |
|
|
|
349 |
|
|
|
350 |
|
|
|
351 |
|
|
|
352 |
|
|
|
353 |
|
|
|
354 |
|
|
|
355 |
|
|
|
356 |
|
|
|
357 |
|
|
|
358 |
|
|
|
328 | def test_parents | |
|
329 | revs1 = [] | |
|
330 | @adapter.revisions('', | |
|
331 | nil, | |
|
332 | "master", | |
|
333 | {:reverse => true}) do |rev| | |
|
334 | revs1 << rev | |
|
335 | end | |
|
336 | assert_equal 15, revs1.length | |
|
337 | assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", | |
|
338 | revs1[0].identifier | |
|
339 | assert_equal nil, revs1[0].parents | |
|
340 | assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9", | |
|
341 | revs1[1].identifier | |
|
342 | assert_equal 1, revs1[1].parents.length | |
|
343 | assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", | |
|
344 | revs1[1].parents[0] | |
|
345 | assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf", | |
|
346 | revs1[10].identifier | |
|
347 | assert_equal 2, revs1[10].parents.length | |
|
348 | assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", | |
|
349 | revs1[10].parents[0] | |
|
350 | assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da", | |
|
351 | revs1[10].parents[1] | |
|
352 | end | |
|
359 | 353 | |
|
360 |
|
|
|
361 |
|
|
|
362 |
|
|
|
363 |
|
|
|
364 |
|
|
|
354 | def test_getting_revisions_with_leading_and_trailing_spaces_in_filename | |
|
355 | assert_equal " filename with a leading space.txt ", | |
|
356 | @adapter.revisions(" filename with a leading space.txt ", | |
|
357 | nil, "master")[0].paths[0][:path] | |
|
358 | end | |
|
365 | 359 | |
|
366 |
|
|
|
367 |
|
|
|
368 |
|
|
|
369 |
|
|
|
370 |
|
|
|
360 | def test_getting_entries_with_leading_and_trailing_spaces_in_filename | |
|
361 | assert_equal " filename with a leading space.txt ", | |
|
362 | @adapter.entries('', | |
|
363 | '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name | |
|
364 | end | |
|
371 | 365 | |
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
|
375 |
|
|
|
376 |
|
|
|
377 |
|
|
|
378 |
|
|
|
379 |
|
|
|
380 |
|
|
|
381 |
|
|
|
366 | def test_annotate | |
|
367 | annotate = @adapter.annotate('sources/watchers_controller.rb') | |
|
368 | assert_kind_of Redmine::Scm::Adapters::Annotate, annotate | |
|
369 | assert_equal 41, annotate.lines.size | |
|
370 | assert_equal "# This program is free software; you can redistribute it and/or", | |
|
371 | annotate.lines[4].strip | |
|
372 | assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", | |
|
373 | annotate.revisions[4].identifier | |
|
374 | assert_equal "jsmith", annotate.revisions[4].author | |
|
375 | end | |
|
382 | 376 | |
|
383 |
|
|
|
384 |
|
|
|
385 |
|
|
|
386 |
|
|
|
387 |
|
|
|
377 | def test_annotate_moved_file | |
|
378 | annotate = @adapter.annotate('renamed_test.txt') | |
|
379 | assert_kind_of Redmine::Scm::Adapters::Annotate, annotate | |
|
380 | assert_equal 2, annotate.lines.size | |
|
381 | end | |
|
388 | 382 | |
|
389 |
|
|
|
390 |
|
|
|
391 |
|
|
|
392 |
|
|
|
393 |
|
|
|
394 |
|
|
|
395 |
|
|
|
396 |
|
|
|
383 | def test_last_rev | |
|
384 | last_rev = @adapter.lastrev("README", | |
|
385 | "4f26664364207fa8b1af9f8722647ab2d4ac5d43") | |
|
386 | assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid | |
|
387 | assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier | |
|
388 | assert_equal "Adam Soltys <asoltys@gmail.com>", last_rev.author | |
|
389 | assert_equal Time.gm(2009, 6, 24, 5, 27, 38), last_rev.time | |
|
390 | end | |
|
397 | 391 | |
|
398 |
|
|
|
399 |
|
|
|
400 |
|
|
|
401 |
|
|
|
402 |
|
|
|
403 |
|
|
|
404 |
|
|
|
405 |
|
|
|
406 |
|
|
|
407 |
|
|
|
392 | def test_last_rev_with_spaces_in_filename | |
|
393 | last_rev = @adapter.lastrev("filemane with spaces.txt", | |
|
394 | "ed5bb786bbda2dee66a2d50faf51429dbc043a7b") | |
|
395 | last_rev_author = last_rev.author | |
|
396 | assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid | |
|
397 | assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier | |
|
398 | assert_equal "#{@str_felix_hex} <felix@fachschaften.org>", | |
|
399 | last_rev.author | |
|
400 | assert_equal Time.gm(2010, 9, 18, 19, 59, 46), last_rev.time | |
|
401 | end | |
|
408 | 402 | |
|
409 |
|
|
|
410 |
|
|
|
411 |
|
|
|
412 |
|
|
|
413 |
|
|
|
414 |
|
|
|
415 |
|
|
|
416 |
|
|
|
417 |
|
|
|
418 |
|
|
|
419 |
|
|
|
420 |
|
|
|
421 |
|
|
|
422 | end | |
|
403 | def test_latin_1_path | |
|
404 | if WINDOWS_PASS | |
|
405 | puts WINDOWS_SKIP_STR | |
|
406 | elsif JRUBY_SKIP | |
|
407 | puts JRUBY_SKIP_STR | |
|
408 | else | |
|
409 | p2 = "latin-1-dir/test-#{@char_1}-2.txt" | |
|
410 | ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1| | |
|
411 | assert @adapter.diff(p2, r1) | |
|
412 | assert @adapter.cat(p2, r1) | |
|
413 | assert_equal 1, @adapter.annotate(p2, r1).lines.length | |
|
414 | ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2| | |
|
415 | assert @adapter.diff(p2, r1, r2) | |
|
423 | 416 | end |
|
424 | 417 | end |
|
425 | 418 | end |
|
419 | end | |
|
426 | 420 | |
|
427 |
|
|
|
428 |
|
|
|
429 |
|
|
|
430 |
|
|
|
431 |
|
|
|
432 |
|
|
|
433 |
|
|
|
434 |
|
|
|
435 |
|
|
|
436 |
|
|
|
437 | end | |
|
421 | def test_latin_1_user_annotate | |
|
422 | ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1| | |
|
423 | annotate = @adapter.annotate(" filename with a leading space.txt ", r1) | |
|
424 | assert_kind_of Redmine::Scm::Adapters::Annotate, annotate | |
|
425 | assert_equal 1, annotate.lines.size | |
|
426 | assert_equal "And this is a file with a leading and trailing space...", | |
|
427 | annotate.lines[0].strip | |
|
428 | assert_equal "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c", | |
|
429 | annotate.revisions[0].identifier | |
|
430 | assert_equal @str_felix_hex, annotate.revisions[0].author | |
|
438 | 431 | end |
|
432 | end | |
|
439 | 433 | |
|
440 |
|
|
|
441 |
|
|
|
442 |
|
|
|
443 |
|
|
|
444 |
|
|
|
445 |
|
|
|
446 |
|
|
|
447 |
|
|
|
448 |
|
|
|
449 |
|
|
|
450 |
|
|
|
451 |
|
|
|
452 |
|
|
|
453 |
|
|
|
454 |
|
|
|
455 |
|
|
|
434 | def test_entries_tag | |
|
435 | entries1 = @adapter.entries(nil, 'tag01.annotated', | |
|
436 | options = {:report_last_commit => true}) | |
|
437 | assert entries1 | |
|
438 | assert_equal 3, entries1.size | |
|
439 | assert_equal 'sources', entries1[1].name | |
|
440 | assert_equal 'sources', entries1[1].path | |
|
441 | assert_equal 'dir', entries1[1].kind | |
|
442 | readme = entries1[2] | |
|
443 | assert_equal 'README', readme.name | |
|
444 | assert_equal 'README', readme.path | |
|
445 | assert_equal 'file', readme.kind | |
|
446 | assert_equal 27, readme.size | |
|
447 | assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier | |
|
448 | assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time | |
|
449 | end | |
|
456 | 450 | |
|
457 |
|
|
|
458 |
|
|
|
459 |
|
|
|
460 |
|
|
|
461 |
|
|
|
462 |
|
|
|
463 |
|
|
|
464 |
|
|
|
465 |
|
|
|
466 |
|
|
|
467 |
|
|
|
468 |
|
|
|
469 |
|
|
|
470 |
|
|
|
471 |
|
|
|
472 |
|
|
|
451 | def test_entries_branch | |
|
452 | entries1 = @adapter.entries(nil, 'test_branch', | |
|
453 | options = {:report_last_commit => true}) | |
|
454 | assert entries1 | |
|
455 | assert_equal 4, entries1.size | |
|
456 | assert_equal 'sources', entries1[1].name | |
|
457 | assert_equal 'sources', entries1[1].path | |
|
458 | assert_equal 'dir', entries1[1].kind | |
|
459 | readme = entries1[2] | |
|
460 | assert_equal 'README', readme.name | |
|
461 | assert_equal 'README', readme.path | |
|
462 | assert_equal 'file', readme.kind | |
|
463 | assert_equal 159, readme.size | |
|
464 | assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier | |
|
465 | assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time | |
|
466 | end | |
|
473 | 467 | |
|
474 |
|
|
|
475 |
|
|
|
476 |
|
|
|
477 |
|
|
|
478 |
|
|
|
479 |
|
|
|
480 |
|
|
|
481 |
|
|
|
482 |
|
|
|
483 |
|
|
|
484 |
|
|
|
485 |
|
|
|
486 |
|
|
|
487 |
|
|
|
488 |
|
|
|
489 |
|
|
|
468 | def test_entries_wrong_path_encoding | |
|
469 | adpt = Redmine::Scm::Adapters::GitAdapter.new( | |
|
470 | REPOSITORY_PATH, | |
|
471 | nil, | |
|
472 | nil, | |
|
473 | nil, | |
|
474 | 'EUC-JP' | |
|
475 | ) | |
|
476 | entries1 = adpt.entries('latin-1-dir', '64f1f3e8') | |
|
477 | assert entries1 | |
|
478 | assert_equal 3, entries1.size | |
|
479 | f1 = entries1[1] | |
|
480 | assert_equal nil, f1.name | |
|
481 | assert_equal nil, f1.path | |
|
482 | assert_equal 'file', f1.kind | |
|
483 | end | |
|
484 | ||
|
485 | def test_entries_latin_1_files | |
|
486 | entries1 = @adapter.entries('latin-1-dir', '64f1f3e8') | |
|
487 | assert entries1 | |
|
488 | assert_equal 3, entries1.size | |
|
489 | f1 = entries1[1] | |
|
490 | assert_equal "test-#{@char_1}-2.txt", f1.name | |
|
491 | assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path | |
|
492 | assert_equal 'file', f1.kind | |
|
493 | end | |
|
490 | 494 | |
|
491 |
|
|
|
492 | entries1 = @adapter.entries('latin-1-dir', '64f1f3e8') | |
|
495 | def test_entries_latin_1_dir | |
|
496 | if WINDOWS_PASS | |
|
497 | puts WINDOWS_SKIP_STR | |
|
498 | elsif JRUBY_SKIP | |
|
499 | puts JRUBY_SKIP_STR | |
|
500 | else | |
|
501 | entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir", | |
|
502 | '1ca7f5ed') | |
|
493 | 503 | assert entries1 |
|
494 | 504 | assert_equal 3, entries1.size |
|
495 | 505 | f1 = entries1[1] |
|
496 | 506 | assert_equal "test-#{@char_1}-2.txt", f1.name |
|
497 | assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path | |
|
507 | assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path | |
|
498 | 508 | assert_equal 'file', f1.kind |
|
499 | 509 | end |
|
510 | end | |
|
500 | 511 | |
|
501 |
|
|
|
502 | if WINDOWS_PASS | |
|
503 | puts WINDOWS_SKIP_STR | |
|
504 | elsif JRUBY_SKIP | |
|
505 | puts JRUBY_SKIP_STR | |
|
506 | else | |
|
507 | entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir", | |
|
508 | '1ca7f5ed') | |
|
509 | assert entries1 | |
|
510 | assert_equal 3, entries1.size | |
|
511 | f1 = entries1[1] | |
|
512 | assert_equal "test-#{@char_1}-2.txt", f1.name | |
|
513 | assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path | |
|
514 | assert_equal 'file', f1.kind | |
|
515 | end | |
|
516 | end | |
|
517 | ||
|
518 | def test_entry | |
|
519 | entry = @adapter.entry() | |
|
520 | assert_equal "", entry.path | |
|
512 | def test_entry | |
|
513 | entry = @adapter.entry() | |
|
514 | assert_equal "", entry.path | |
|
515 | assert_equal "dir", entry.kind | |
|
516 | entry = @adapter.entry('') | |
|
517 | assert_equal "", entry.path | |
|
518 | assert_equal "dir", entry.kind | |
|
519 | assert_nil @adapter.entry('invalid') | |
|
520 | assert_nil @adapter.entry('/invalid') | |
|
521 | assert_nil @adapter.entry('/invalid/') | |
|
522 | assert_nil @adapter.entry('invalid/invalid') | |
|
523 | assert_nil @adapter.entry('invalid/invalid/') | |
|
524 | assert_nil @adapter.entry('/invalid/invalid') | |
|
525 | assert_nil @adapter.entry('/invalid/invalid/') | |
|
526 | ["README", "/README"].each do |path| | |
|
527 | entry = @adapter.entry(path, '7234cb2750b63f') | |
|
528 | assert_equal "README", entry.path | |
|
529 | assert_equal "file", entry.kind | |
|
530 | end | |
|
531 | ["sources", "/sources", "/sources/"].each do |path| | |
|
532 | entry = @adapter.entry(path, '7234cb2750b63f') | |
|
533 | assert_equal "sources", entry.path | |
|
521 | 534 | assert_equal "dir", entry.kind |
|
522 | entry = @adapter.entry('') | |
|
523 | assert_equal "", entry.path | |
|
524 | assert_equal "dir", entry.kind | |
|
525 | assert_nil @adapter.entry('invalid') | |
|
526 | assert_nil @adapter.entry('/invalid') | |
|
527 | assert_nil @adapter.entry('/invalid/') | |
|
528 | assert_nil @adapter.entry('invalid/invalid') | |
|
529 | assert_nil @adapter.entry('invalid/invalid/') | |
|
530 | assert_nil @adapter.entry('/invalid/invalid') | |
|
531 | assert_nil @adapter.entry('/invalid/invalid/') | |
|
532 | ["README", "/README"].each do |path| | |
|
533 | entry = @adapter.entry(path, '7234cb2750b63f') | |
|
534 | assert_equal "README", entry.path | |
|
535 | assert_equal "file", entry.kind | |
|
536 | end | |
|
537 | ["sources", "/sources", "/sources/"].each do |path| | |
|
538 | entry = @adapter.entry(path, '7234cb2750b63f') | |
|
539 | assert_equal "sources", entry.path | |
|
540 | assert_equal "dir", entry.kind | |
|
541 | end | |
|
542 | ["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path| | |
|
543 | entry = @adapter.entry(path, '7234cb2750b63f') | |
|
544 | assert_equal "sources/watchers_controller.rb", entry.path | |
|
545 | assert_equal "file", entry.kind | |
|
546 | end | |
|
547 | 535 | end |
|
548 | ||
|
549 | def test_path_encoding_default_utf8 | |
|
550 | adpt1 = Redmine::Scm::Adapters::GitAdapter.new( | |
|
551 | REPOSITORY_PATH | |
|
552 | ) | |
|
553 | assert_equal "UTF-8", adpt1.path_encoding | |
|
554 | adpt2 = Redmine::Scm::Adapters::GitAdapter.new( | |
|
555 | REPOSITORY_PATH, | |
|
556 | nil, | |
|
557 | nil, | |
|
558 | nil, | |
|
559 | "" | |
|
560 | ) | |
|
561 | assert_equal "UTF-8", adpt2.path_encoding | |
|
536 | ["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path| | |
|
537 | entry = @adapter.entry(path, '7234cb2750b63f') | |
|
538 | assert_equal "sources/watchers_controller.rb", entry.path | |
|
539 | assert_equal "file", entry.kind | |
|
562 | 540 | end |
|
541 | end | |
|
563 | 542 | |
|
564 |
|
|
|
565 | assert_nil @adapter.cat('invalid') | |
|
566 | end | |
|
543 | def test_path_encoding_default_utf8 | |
|
544 | adpt1 = Redmine::Scm::Adapters::GitAdapter.new( | |
|
545 | REPOSITORY_PATH | |
|
546 | ) | |
|
547 | assert_equal "UTF-8", adpt1.path_encoding | |
|
548 | adpt2 = Redmine::Scm::Adapters::GitAdapter.new( | |
|
549 | REPOSITORY_PATH, | |
|
550 | nil, | |
|
551 | nil, | |
|
552 | nil, | |
|
553 | "" | |
|
554 | ) | |
|
555 | assert_equal "UTF-8", adpt2.path_encoding | |
|
556 | end | |
|
567 | 557 | |
|
568 |
|
|
|
569 |
|
|
|
570 | assert_nil @adapter.cat('README', '1234abcd5678') | |
|
571 | end | |
|
558 | def test_cat_path_invalid | |
|
559 | assert_nil @adapter.cat('invalid') | |
|
560 | end | |
|
572 | 561 | |
|
573 |
|
|
|
574 | assert_equal [], @adapter.diff('invalid', '713f4944648826f5') | |
|
575 | end | |
|
562 | def test_cat_revision_invalid | |
|
563 | assert @adapter.cat('README') | |
|
564 | assert_nil @adapter.cat('README', '1234abcd5678') | |
|
565 | end | |
|
576 | 566 | |
|
577 |
|
|
|
578 |
|
|
|
579 | assert_nil @adapter.diff(nil, '713f4944648826f5', '1234abcd5678') | |
|
580 | assert_nil @adapter.diff(nil, '1234abcd5678', '713f4944648826f5') | |
|
581 | end | |
|
567 | def test_diff_path_invalid | |
|
568 | assert_equal [], @adapter.diff('invalid', '713f4944648826f5') | |
|
569 | end | |
|
582 | 570 | |
|
583 |
|
|
|
584 |
|
|
|
585 | end | |
|
571 | def test_diff_revision_invalid | |
|
572 | assert_nil @adapter.diff(nil, '1234abcd5678') | |
|
573 | assert_nil @adapter.diff(nil, '713f4944648826f5', '1234abcd5678') | |
|
574 | assert_nil @adapter.diff(nil, '1234abcd5678', '713f4944648826f5') | |
|
575 | end | |
|
586 | 576 | |
|
587 |
|
|
|
588 |
|
|
|
589 | assert_nil @adapter.annotate('README', '1234abcd5678') | |
|
590 | end | |
|
577 | def test_annotate_path_invalid | |
|
578 | assert_nil @adapter.annotate('invalid') | |
|
579 | end | |
|
591 | 580 | |
|
592 | private | |
|
581 | def test_annotate_revision_invalid | |
|
582 | assert @adapter.annotate('README') | |
|
583 | assert_nil @adapter.annotate('README', '1234abcd5678') | |
|
584 | end | |
|
593 | 585 | |
|
594 | def test_scm_version_for(scm_command_version, version) | |
|
595 | @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version) | |
|
596 | assert_equal version, @adapter.class.scm_command_version | |
|
597 | end | |
|
586 | private | |
|
598 | 587 | |
|
599 | else | |
|
600 | puts "Git test repository NOT FOUND. Skipping unit tests !!!" | |
|
601 | def test_fake; assert true end | |
|
588 | def test_scm_version_for(scm_command_version, version) | |
|
589 | @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version) | |
|
590 | assert_equal version, @adapter.class.scm_command_version | |
|
602 | 591 | end |
|
603 | end | |
|
604 | 592 | |
|
605 | rescue LoadError | |
|
606 | class GitMochaFake < ActiveSupport::TestCase | |
|
607 |
def test_fake; assert |
|
|
593 | else | |
|
594 | puts "Git test repository NOT FOUND. Skipping unit tests !!!" | |
|
595 | def test_fake; assert true end | |
|
608 | 596 | end |
|
609 | 597 | end |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed | |
This diff has been collapsed as it changes many lines, (1098 lines changed) Show them Hide them |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now