# HG changeset patch
# User Chris Cannam
# Date 1410251311 -3600
# Node ID b450a9d58aedc637ab24eff22ddec55048cd01c2
# Parent e248c7af89ecdc5a4c5bedafdb7c6d357643873e
Update to Redmine SVN revision 13356 on 2.4-stable branch
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/00/0009a621965fc195e93ba67a7d3500cbcd38b084.svn-base
--- a/.svn/pristine/00/0009a621965fc195e93ba67a7d3500cbcd38b084.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-class DocumentsController < ApplicationController
- default_search_scope :documents
- model_object Document
- before_filter :find_project_by_project_id, :only => [:index, :new, :create]
- before_filter :find_model_object, :except => [:index, :new, :create]
- before_filter :find_project_from_association, :except => [:index, :new, :create]
- before_filter :authorize
-
- helper :attachments
-
- def index
- @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
- documents = @project.documents.includes(:attachments, :category).all
- case @sort_by
- when 'date'
- @grouped = documents.group_by {|d| d.updated_on.to_date }
- when 'title'
- @grouped = documents.group_by {|d| d.title.first.upcase}
- when 'author'
- @grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
- else
- @grouped = documents.group_by(&:category)
- end
- @document = @project.documents.build
- render :layout => false if request.xhr?
- end
-
- def show
- @attachments = @document.attachments.all
- end
-
- def new
- @document = @project.documents.build
- @document.safe_attributes = params[:document]
- end
-
- def create
- @document = @project.documents.build
- @document.safe_attributes = params[:document]
- @document.save_attachments(params[:attachments])
- if @document.save
- render_attachment_warning_if_needed(@document)
- flash[:notice] = l(:notice_successful_create)
- redirect_to project_documents_path(@project)
- else
- render :action => 'new'
- end
- end
-
- def edit
- end
-
- def update
- @document.safe_attributes = params[:document]
- if request.put? and @document.save
- flash[:notice] = l(:notice_successful_update)
- redirect_to document_path(@document)
- else
- render :action => 'edit'
- end
- end
-
- def destroy
- @document.destroy if request.delete?
- redirect_to project_documents_path(@project)
- end
-
- def add_attachment
- attachments = Attachment.attach_files(@document, params[:attachments])
- render_attachment_warning_if_needed(@document)
-
- if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
- Mailer.attachments_added(attachments[:files]).deliver
- end
- redirect_to document_path(@document)
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/01/019777b51c435b18c756e5573fde25c903195b68.svn-base
--- a/.svn/pristine/01/019777b51c435b18c756e5573fde25c903195b68.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-require 'rexml/document'
-
-module Redmine
- module VERSION #:nodoc:
- MAJOR = 2
- MINOR = 4
- TINY = 2
-
- # Branch values:
- # * official release: nil
- # * stable branch: stable
- # * trunk: devel
- BRANCH = 'stable'
-
- # Retrieves the revision from the working copy
- def self.revision
- if File.directory?(File.join(Rails.root, '.svn'))
- begin
- path = Redmine::Scm::Adapters::AbstractAdapter.shell_quote(Rails.root.to_s)
- if `svn info --xml #{path}` =~ /revision="(\d+)"/
- return $1.to_i
- end
- rescue
- # Could not find the current revision
- end
- end
- nil
- end
-
- REVISION = self.revision
- ARRAY = [MAJOR, MINOR, TINY, BRANCH, REVISION].compact
- STRING = ARRAY.join('.')
-
- def self.to_a; ARRAY end
- def self.to_s; STRING end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/01/01b21d04c9e912327dc0059ef282ceb1a603f54f.svn-base
--- a/.svn/pristine/01/01b21d04c9e912327dc0059ef282ceb1a603f54f.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AutoCompletesControllerTest < ActionController::TestCase
- fixtures :projects, :issues, :issue_statuses,
- :enumerations, :users, :issue_categories,
- :trackers,
- :projects_trackers,
- :roles,
- :member_roles,
- :members,
- :enabled_modules,
- :journals, :journal_details
-
- def test_issues_should_not_be_case_sensitive
- get :issues, :project_id => 'ecookbook', :q => 'ReCiPe'
- assert_response :success
- assert_not_nil assigns(:issues)
- assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
- end
-
- def test_issues_should_accept_term_param
- get :issues, :project_id => 'ecookbook', :term => 'ReCiPe'
- assert_response :success
- assert_not_nil assigns(:issues)
- assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
- end
-
- def test_issues_should_return_issue_with_given_id
- get :issues, :project_id => 'subproject1', :q => '13'
- assert_response :success
- assert_not_nil assigns(:issues)
- assert assigns(:issues).include?(Issue.find(13))
- end
-
- def test_issues_should_return_issue_with_given_id_preceded_with_hash
- get :issues, :project_id => 'subproject1', :q => '#13'
- assert_response :success
- assert_not_nil assigns(:issues)
- assert assigns(:issues).include?(Issue.find(13))
- end
-
- def test_auto_complete_with_scope_all_should_search_other_projects
- get :issues, :project_id => 'ecookbook', :q => '13', :scope => 'all'
- assert_response :success
- assert_not_nil assigns(:issues)
- assert assigns(:issues).include?(Issue.find(13))
- end
-
- def test_auto_complete_without_project_should_search_all_projects
- get :issues, :q => '13'
- assert_response :success
- assert_not_nil assigns(:issues)
- assert assigns(:issues).include?(Issue.find(13))
- end
-
- def test_auto_complete_without_scope_all_should_not_search_other_projects
- get :issues, :project_id => 'ecookbook', :q => '13'
- assert_response :success
- assert_equal [], assigns(:issues)
- end
-
- def test_issues_should_return_json
- get :issues, :project_id => 'subproject1', :q => '13'
- assert_response :success
- json = ActiveSupport::JSON.decode(response.body)
- assert_kind_of Array, json
- issue = json.first
- assert_kind_of Hash, issue
- assert_equal 13, issue['id']
- assert_equal 13, issue['value']
- assert_equal 'Bug #13: Subproject issue two', issue['label']
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/01/01cfbfdc38592dff3cbe5b1b36118aa0e1e65223.svn-base
--- a/.svn/pristine/01/01cfbfdc38592dff3cbe5b1b36118aa0e1e65223.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class GanttsControllerTest < ActionController::TestCase
- fixtures :projects, :trackers, :issue_statuses, :issues,
- :enumerations, :users, :issue_categories,
- :projects_trackers,
- :roles,
- :member_roles,
- :members,
- :enabled_modules,
- :versions
-
- def test_gantt_should_work
- i2 = Issue.find(2)
- i2.update_attribute(:due_date, 1.month.from_now)
- get :show, :project_id => 1
- assert_response :success
- assert_template 'gantts/show'
- assert_not_nil assigns(:gantt)
- # Issue with start and due dates
- i = Issue.find(1)
- assert_not_nil i.due_date
- assert_select "div a.issue", /##{i.id}/
- # Issue with on a targeted version should not be in the events but loaded in the html
- i = Issue.find(2)
- assert_select "div a.issue", /##{i.id}/
- end
-
- def test_gantt_should_work_without_issue_due_dates
- Issue.update_all("due_date = NULL")
- get :show, :project_id => 1
- assert_response :success
- assert_template 'gantts/show'
- assert_not_nil assigns(:gantt)
- end
-
- def test_gantt_should_work_without_issue_and_version_due_dates
- Issue.update_all("due_date = NULL")
- Version.update_all("effective_date = NULL")
- get :show, :project_id => 1
- assert_response :success
- assert_template 'gantts/show'
- assert_not_nil assigns(:gantt)
- end
-
- def test_gantt_should_work_cross_project
- get :show
- assert_response :success
- assert_template 'gantts/show'
- assert_not_nil assigns(:gantt)
- assert_not_nil assigns(:gantt).query
- assert_nil assigns(:gantt).project
- end
-
- def test_gantt_should_not_disclose_private_projects
- get :show
- assert_response :success
- assert_template 'gantts/show'
- assert_tag 'a', :content => /eCookbook/
- # Root private project
- assert_no_tag 'a', {:content => /OnlineStore/}
- # Private children of a public project
- assert_no_tag 'a', :content => /Private child of eCookbook/
- end
-
- def test_gantt_should_display_relations
- IssueRelation.delete_all
- issue1 = Issue.generate!(:start_date => 1.day.from_now.to_date, :due_date => 3.day.from_now.to_date)
- issue2 = Issue.generate!(:start_date => 1.day.from_now.to_date, :due_date => 3.day.from_now.to_date)
- IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => 'precedes')
-
- get :show
- assert_response :success
-
- relations = assigns(:gantt).relations
- assert_kind_of Hash, relations
- assert relations.present?
- assert_select 'div.task_todo[id=?][data-rels*=?]', "task-todo-issue-#{issue1.id}", issue2.id.to_s
- assert_select 'div.task_todo[id=?]:not([data-rels])', "task-todo-issue-#{issue2.id}"
- end
-
- def test_gantt_should_export_to_pdf
- get :show, :project_id => 1, :format => 'pdf'
- assert_response :success
- assert_equal 'application/pdf', @response.content_type
- assert @response.body.starts_with?('%PDF')
- assert_not_nil assigns(:gantt)
- end
-
- def test_gantt_should_export_to_pdf_cross_project
- get :show, :format => 'pdf'
- assert_response :success
- assert_equal 'application/pdf', @response.content_type
- assert @response.body.starts_with?('%PDF')
- assert_not_nil assigns(:gantt)
- end
-
- if Object.const_defined?(:Magick)
- def test_gantt_should_export_to_png
- get :show, :project_id => 1, :format => 'png'
- assert_response :success
- assert_equal 'image/png', @response.content_type
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/02/027410b40ae4e2d4f4be0368cf13b4cdb0164b5f.svn-base
--- a/.svn/pristine/02/027410b40ae4e2d4f4be0368cf13b4cdb0164b5f.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RoleTest < ActiveSupport::TestCase
- fixtures :roles, :workflows, :trackers
-
- def test_sorted_scope
- assert_equal Role.all.sort, Role.sorted.all
- end
-
- def test_givable_scope
- assert_equal Role.all.reject(&:builtin?).sort, Role.givable.all
- end
-
- def test_builtin_scope
- assert_equal Role.all.select(&:builtin?).sort, Role.builtin(true).all.sort
- assert_equal Role.all.reject(&:builtin?).sort, Role.builtin(false).all.sort
- end
-
- def test_copy_from
- role = Role.find(1)
- copy = Role.new.copy_from(role)
-
- assert_nil copy.id
- assert_equal '', copy.name
- assert_equal role.permissions, copy.permissions
-
- copy.name = 'Copy'
- assert copy.save
- end
-
- def test_copy_workflows
- source = Role.find(1)
- assert_equal 90, source.workflow_rules.size
-
- target = Role.new(:name => 'Target')
- assert target.save
- target.workflow_rules.copy(source)
- target.reload
- assert_equal 90, target.workflow_rules.size
- end
-
- def test_permissions_should_be_unserialized_with_its_coder
- Role::PermissionsAttributeCoder.expects(:load).once
- Role.find(1).permissions
- end
-
- def test_add_permission
- role = Role.find(1)
- size = role.permissions.size
- role.add_permission!("apermission", "anotherpermission")
- role.reload
- assert role.permissions.include?(:anotherpermission)
- assert_equal size + 2, role.permissions.size
- end
-
- def test_remove_permission
- role = Role.find(1)
- size = role.permissions.size
- perm = role.permissions[0..1]
- role.remove_permission!(*perm)
- role.reload
- assert ! role.permissions.include?(perm[0])
- assert_equal size - 2, role.permissions.size
- end
-
- def test_name
- I18n.locale = 'fr'
- assert_equal 'Manager', Role.find(1).name
- assert_equal 'Anonyme', Role.anonymous.name
- assert_equal 'Non membre', Role.non_member.name
- end
-
- def test_find_all_givable
- assert_equal Role.all.reject(&:builtin?).sort, Role.find_all_givable
- end
-
- def test_anonymous_should_return_the_anonymous_role
- assert_no_difference('Role.count') do
- role = Role.anonymous
- assert role.builtin?
- assert_equal Role::BUILTIN_ANONYMOUS, role.builtin
- end
- end
-
- def test_anonymous_with_a_missing_anonymous_role_should_return_the_anonymous_role
- Role.where(:builtin => Role::BUILTIN_ANONYMOUS).delete_all
-
- assert_difference('Role.count') do
- role = Role.anonymous
- assert role.builtin?
- assert_equal Role::BUILTIN_ANONYMOUS, role.builtin
- end
- end
-
- def test_non_member_should_return_the_non_member_role
- assert_no_difference('Role.count') do
- role = Role.non_member
- assert role.builtin?
- assert_equal Role::BUILTIN_NON_MEMBER, role.builtin
- end
- end
-
- def test_non_member_with_a_missing_non_member_role_should_return_the_non_member_role
- Role.where(:builtin => Role::BUILTIN_NON_MEMBER).delete_all
-
- assert_difference('Role.count') do
- role = Role.non_member
- assert role.builtin?
- assert_equal Role::BUILTIN_NON_MEMBER, role.builtin
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/02/02fe391dd14e50d29ad45f8bf8dea30be02556c5.svn-base
--- a/.svn/pristine/02/02fe391dd14e50d29ad45f8bf8dea30be02556c5.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module Redmine
- module Themes
-
- # Return an array of installed themes
- def self.themes
- @@installed_themes ||= scan_themes
- end
-
- # Rescan themes directory
- def self.rescan
- @@installed_themes = scan_themes
- end
-
- # Return theme for given id, or nil if it's not found
- def self.theme(id, options={})
- return nil if id.blank?
-
- found = themes.find {|t| t.id == id}
- if found.nil? && options[:rescan] != false
- rescan
- found = theme(id, :rescan => false)
- end
- found
- end
-
- # Class used to represent a theme
- class Theme
- attr_reader :path, :name, :dir
-
- def initialize(path)
- @path = path
- @dir = File.basename(path)
- @name = @dir.humanize
- @stylesheets = nil
- @javascripts = nil
- end
-
- # Directory name used as the theme id
- def id; dir end
-
- def ==(theme)
- theme.is_a?(Theme) && theme.dir == dir
- end
-
- def <=>(theme)
- name <=> theme.name
- end
-
- def stylesheets
- @stylesheets ||= assets("stylesheets", "css")
- end
-
- def images
- @images ||= assets("images")
- end
-
- def javascripts
- @javascripts ||= assets("javascripts", "js")
- end
-
- def stylesheet_path(source)
- "/themes/#{dir}/stylesheets/#{source}"
- end
-
- def image_path(source)
- "/themes/#{dir}/images/#{source}"
- end
-
- def javascript_path(source)
- "/themes/#{dir}/javascripts/#{source}"
- end
-
- private
-
- def assets(dir, ext=nil)
- if ext
- Dir.glob("#{path}/#{dir}/*.#{ext}").collect {|f| File.basename(f).gsub(/\.#{ext}$/, '')}
- else
- Dir.glob("#{path}/#{dir}/*").collect {|f| File.basename(f)}
- end
- end
- end
-
- private
-
- def self.scan_themes
- dirs = Dir.glob("#{Rails.public_path}/themes/*").select do |f|
- # A theme should at least override application.css
- File.directory?(f) && File.exist?("#{f}/stylesheets/application.css")
- end
- dirs.collect {|dir| Theme.new(dir)}.sort
- end
- end
-end
-
-module ApplicationHelper
- def current_theme
- unless instance_variable_defined?(:@current_theme)
- @current_theme = Redmine::Themes.theme(Setting.ui_theme)
- end
- @current_theme
- end
-
- # Returns the header tags for the current theme
- def heads_for_theme
- if current_theme && current_theme.javascripts.include?('theme')
- javascript_include_tag current_theme.javascript_path('theme')
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/03/0335a712dd5fb2c44f8cb6daaf182ac72aee4c7f.svn-base
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/03/0335a712dd5fb2c44f8cb6daaf182ac72aee4c7f.svn-base Tue Sep 09 09:28:31 2014 +0100
@@ -0,0 +1,287 @@
+
+
+
+Redmine 為每一種標題指定一個 HTML 錨定 (anchor) ,因此您可使用 "#Heading" 、 "#Subheading" 等方式連結至這些標題。
+
+
+ ' + content_tag('p', link_to_issue(ancestor, :project => (issue.project_id != ancestor.project_id)))
- end
- s << '
'
- subject = h(issue.subject)
- if issue.is_private?
- subject = content_tag('span', l(:field_is_private), :class => 'private') + ' ' + subject
- end
- s << content_tag('h3', subject)
- s << '
' * (ancestors.size + 1)
- s.html_safe
- end
-
- def render_descendants_tree(issue)
- s = '
'
- s.html_safe
- end
-
- # Returns an array of error messages for bulk edited issues
- def bulk_edit_error_messages(issues)
- messages = {}
- issues.each do |issue|
- issue.errors.full_messages.each do |message|
- messages[message] ||= []
- messages[message] << issue
- end
- end
- messages.map { |message, issues|
- "#{message}: " + issues.map {|i| "##{i.id}"}.join(', ')
- }
- end
-
- # Returns a link for adding a new subtask to the given issue
- def link_to_new_subtask(issue)
- attrs = {
- :tracker_id => issue.tracker,
- :parent_issue_id => issue
- }
- link_to(l(:button_add), new_project_issue_path(issue.project, :issue => attrs))
- end
-
- class IssueFieldsRows
- include ActionView::Helpers::TagHelper
-
- def initialize
- @left = []
- @right = []
- end
-
- def left(*args)
- args.any? ? @left << cells(*args) : @left
- end
-
- def right(*args)
- args.any? ? @right << cells(*args) : @right
- end
-
- def size
- @left.size > @right.size ? @left.size : @right.size
- end
-
- def to_html
- html = ''.html_safe
- blank = content_tag('th', '') + content_tag('td', '')
- size.times do |i|
- left = @left[i] || blank
- right = @right[i] || blank
- html << content_tag('tr', left + right)
- end
- html
- end
-
- def cells(label, text, options={})
- content_tag('th', "#{label}:", options) + content_tag('td', text, options)
- end
- end
-
- def issue_fields_rows
- r = IssueFieldsRows.new
- yield r
- r.to_html
- end
-
- def render_custom_fields_rows(issue)
- values = issue.visible_custom_field_values
- return if values.empty?
- ordered_values = []
- half = (values.size / 2.0).ceil
- half.times do |i|
- ordered_values << values[i]
- ordered_values << values[i + half]
- end
- s = "
\n"
- n = 0
- ordered_values.compact.each do |value|
- s << "
\n
\n" if n > 0 && (n % 2) == 0
- s << "\t#{ h(value.custom_field.name) }: | #{ simple_format_without_paragraph(h(show_value(value))) } | \n"
- n += 1
- end
- s << "
\n"
- s.html_safe
- end
-
- def issues_destroy_confirmation_message(issues)
- issues = [issues] unless issues.is_a?(Array)
- message = l(:text_issues_destroy_confirmation)
- descendant_count = issues.inject(0) {|memo, i| memo += (i.right - i.left - 1)/2}
- if descendant_count > 0
- issues.each do |issue|
- next if issue.root?
- issues.each do |other_issue|
- descendant_count -= 1 if issue.is_descendant_of?(other_issue)
- end
- end
- if descendant_count > 0
- message << "\n" + l(:text_issues_destroy_descendants_confirmation, :count => descendant_count)
- end
- end
- message
- end
-
- def sidebar_queries
- unless @sidebar_queries
- @sidebar_queries = IssueQuery.visible.
- order("#{Query.table_name}.name ASC").
- # Project specific queries and global queries
- where(@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id]).
- all
- end
- @sidebar_queries
- end
-
- def query_links(title, queries)
- return '' if queries.empty?
- # links to #index on issues/show
- url_params = controller_name == 'issues' ? {:controller => 'issues', :action => 'index', :project_id => @project} : params
-
- content_tag('h3', title) + "\n" +
- content_tag('ul',
- queries.collect {|query|
- css = 'query'
- css << ' selected' if query == @query
- content_tag('li', link_to(query.name, url_params.merge(:query_id => query), :class => css))
- }.join("\n").html_safe,
- :class => 'queries'
- ) + "\n"
- end
-
- def render_sidebar_queries
- out = ''.html_safe
- out << query_links(l(:label_my_queries), sidebar_queries.select(&:is_private?))
- out << query_links(l(:label_query_plural), sidebar_queries.reject(&:is_private?))
- out
- end
-
- def email_issue_attributes(issue, user)
- items = []
- %w(author status priority assigned_to category fixed_version).each do |attribute|
- unless issue.disabled_core_fields.include?(attribute+"_id")
- items << "#{l("field_#{attribute}")}: #{issue.send attribute}"
- end
- end
- issue.visible_custom_field_values(user).each do |value|
- items << "#{value.custom_field.name}: #{show_value(value)}"
- end
- items
- end
-
- def render_email_issue_attributes(issue, user, html=false)
- items = email_issue_attributes(issue, user)
- if html
- content_tag('ul', items.map{|s| content_tag('li', s)}.join("\n").html_safe)
- else
- items.map{|s| "* #{s}"}.join("\n")
- end
- end
-
- # Returns the textual representation of a journal details
- # as an array of strings
- def details_to_strings(details, no_html=false, options={})
- options[:only_path] = (options[:only_path] == false ? false : true)
- strings = []
- values_by_field = {}
- details.each do |detail|
- if detail.property == 'cf'
- field = detail.custom_field
- if field && field.multiple?
- values_by_field[field] ||= {:added => [], :deleted => []}
- if detail.old_value
- values_by_field[field][:deleted] << detail.old_value
- end
- if detail.value
- values_by_field[field][:added] << detail.value
- end
- next
- end
- end
- strings << show_detail(detail, no_html, options)
- end
- values_by_field.each do |field, changes|
- detail = JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s)
- detail.instance_variable_set "@custom_field", field
- if changes[:added].any?
- detail.value = changes[:added]
- strings << show_detail(detail, no_html, options)
- elsif changes[:deleted].any?
- detail.old_value = changes[:deleted]
- strings << show_detail(detail, no_html, options)
- end
- end
- strings
- end
-
- # Returns the textual representation of a single journal detail
- def show_detail(detail, no_html=false, options={})
- multiple = false
- case detail.property
- when 'attr'
- field = detail.prop_key.to_s.gsub(/\_id$/, "")
- label = l(("field_" + field).to_sym)
- case detail.prop_key
- when 'due_date', 'start_date'
- value = format_date(detail.value.to_date) if detail.value
- old_value = format_date(detail.old_value.to_date) if detail.old_value
-
- when 'project_id', 'status_id', 'tracker_id', 'assigned_to_id',
- 'priority_id', 'category_id', 'fixed_version_id'
- value = find_name_by_reflection(field, detail.value)
- old_value = find_name_by_reflection(field, detail.old_value)
-
- when 'estimated_hours'
- value = "%0.02f" % detail.value.to_f unless detail.value.blank?
- old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
-
- when 'parent_id'
- label = l(:field_parent_issue)
- value = "##{detail.value}" unless detail.value.blank?
- old_value = "##{detail.old_value}" unless detail.old_value.blank?
-
- when 'is_private'
- value = l(detail.value == "0" ? :general_text_No : :general_text_Yes) unless detail.value.blank?
- old_value = l(detail.old_value == "0" ? :general_text_No : :general_text_Yes) unless detail.old_value.blank?
- end
- when 'cf'
- custom_field = detail.custom_field
- if custom_field
- multiple = custom_field.multiple?
- label = custom_field.name
- value = format_value(detail.value, custom_field.field_format) if detail.value
- old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
- end
- when 'attachment'
- label = l(:label_attachment)
- when 'relation'
- if detail.value && !detail.old_value
- rel_issue = Issue.visible.find_by_id(detail.value)
- value = rel_issue.nil? ? "#{l(:label_issue)} ##{detail.value}" :
- (no_html ? rel_issue : link_to_issue(rel_issue, :only_path => options[:only_path]))
- elsif detail.old_value && !detail.value
- rel_issue = Issue.visible.find_by_id(detail.old_value)
- old_value = rel_issue.nil? ? "#{l(:label_issue)} ##{detail.old_value}" :
- (no_html ? rel_issue : link_to_issue(rel_issue, :only_path => options[:only_path]))
- end
- label = l(detail.prop_key.to_sym)
- end
- call_hook(:helper_issues_show_detail_after_setting,
- {:detail => detail, :label => label, :value => value, :old_value => old_value })
-
- label ||= detail.prop_key
- value ||= detail.value
- old_value ||= detail.old_value
-
- unless no_html
- label = content_tag('strong', label)
- old_value = content_tag("i", h(old_value)) if detail.old_value
- if detail.old_value && detail.value.blank? && detail.property != 'relation'
- old_value = content_tag("del", old_value)
- end
- if detail.property == 'attachment' && !value.blank? && atta = Attachment.find_by_id(detail.prop_key)
- # Link to the attachment if it has not been removed
- value = link_to_attachment(atta, :download => true, :only_path => options[:only_path])
- if options[:only_path] != false && atta.is_text?
- value += link_to(
- image_tag('magnifier.png'),
- :controller => 'attachments', :action => 'show',
- :id => atta, :filename => atta.filename
- )
- end
- else
- value = content_tag("i", h(value)) if value
- end
- end
-
- if detail.property == 'attr' && detail.prop_key == 'description'
- s = l(:text_journal_changed_no_detail, :label => label)
- unless no_html
- diff_link = link_to 'diff',
- {:controller => 'journals', :action => 'diff', :id => detail.journal_id,
- :detail_id => detail.id, :only_path => options[:only_path]},
- :title => l(:label_view_diff)
- s << " (#{ diff_link })"
- end
- s.html_safe
- elsif detail.value.present?
- case detail.property
- when 'attr', 'cf'
- if detail.old_value.present?
- l(:text_journal_changed, :label => label, :old => old_value, :new => value).html_safe
- elsif multiple
- l(:text_journal_added, :label => label, :value => value).html_safe
- else
- l(:text_journal_set_to, :label => label, :value => value).html_safe
- end
- when 'attachment', 'relation'
- l(:text_journal_added, :label => label, :value => value).html_safe
- end
- else
- l(:text_journal_deleted, :label => label, :old => old_value).html_safe
- end
- end
-
- # Find the name of an associated record stored in the field attribute
- def find_name_by_reflection(field, id)
- unless id.present?
- return nil
- end
- association = Issue.reflect_on_association(field.to_sym)
- if association
- record = association.class_name.constantize.find_by_id(id)
- if record
- record.name.force_encoding('UTF-8') if record.name.respond_to?(:force_encoding)
- return record.name
- end
- end
- end
-
- # Renders issue children recursively
- def render_api_issue_children(issue, api)
- return if issue.leaf?
- api.array :children do
- issue.children.each do |child|
- api.issue(:id => child.id) do
- api.tracker(:id => child.tracker_id, :name => child.tracker.name) unless child.tracker.nil?
- api.subject child.subject
- render_api_issue_children(child, api)
- end
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/06/06efa9c81bf4ffa47e3211023e46fcb09d4eac0f.svn-base
--- a/.svn/pristine/06/06efa9c81bf4ffa47e3211023e46fcb09d4eac0f.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RolesControllerTest < ActionController::TestCase
- fixtures :roles, :users, :members, :member_roles, :workflows, :trackers
-
- def setup
- User.current = nil
- @request.session[:user_id] = 1 # admin
- end
-
- def test_index
- get :index
- assert_response :success
- assert_template 'index'
-
- assert_not_nil assigns(:roles)
- assert_equal Role.order('builtin, position').all, assigns(:roles)
-
- assert_tag :tag => 'a', :attributes => { :href => '/roles/1/edit' },
- :content => 'Manager'
- end
-
- def test_new
- get :new
- assert_response :success
- assert_template 'new'
- end
-
- def test_new_with_copy
- copy_from = Role.find(2)
-
- get :new, :copy => copy_from.id.to_s
- assert_response :success
- assert_template 'new'
-
- role = assigns(:role)
- assert_equal copy_from.permissions, role.permissions
-
- assert_select 'form' do
- # blank name
- assert_select 'input[name=?][value=]', 'role[name]'
- # edit_project permission checked
- assert_select 'input[type=checkbox][name=?][value=edit_project][checked=checked]', 'role[permissions][]'
- # add_project permission not checked
- assert_select 'input[type=checkbox][name=?][value=add_project]', 'role[permissions][]'
- assert_select 'input[type=checkbox][name=?][value=add_project][checked=checked]', 'role[permissions][]', 0
- # workflow copy selected
- assert_select 'select[name=?]', 'copy_workflow_from' do
- assert_select 'option[value=2][selected=selected]'
- end
- end
- end
-
- def test_create_with_validaton_failure
- post :create, :role => {:name => '',
- :permissions => ['add_issues', 'edit_issues', 'log_time', ''],
- :assignable => '0'}
-
- assert_response :success
- assert_template 'new'
- assert_tag :tag => 'div', :attributes => { :id => 'errorExplanation' }
- end
-
- def test_create_without_workflow_copy
- post :create, :role => {:name => 'RoleWithoutWorkflowCopy',
- :permissions => ['add_issues', 'edit_issues', 'log_time', ''],
- :assignable => '0'}
-
- assert_redirected_to '/roles'
- role = Role.find_by_name('RoleWithoutWorkflowCopy')
- assert_not_nil role
- assert_equal [:add_issues, :edit_issues, :log_time], role.permissions
- assert !role.assignable?
- end
-
- def test_create_with_workflow_copy
- post :create, :role => {:name => 'RoleWithWorkflowCopy',
- :permissions => ['add_issues', 'edit_issues', 'log_time', ''],
- :assignable => '0'},
- :copy_workflow_from => '1'
-
- assert_redirected_to '/roles'
- role = Role.find_by_name('RoleWithWorkflowCopy')
- assert_not_nil role
- assert_equal Role.find(1).workflow_rules.size, role.workflow_rules.size
- end
-
- def test_edit
- get :edit, :id => 1
- assert_response :success
- assert_template 'edit'
- assert_equal Role.find(1), assigns(:role)
- assert_select 'select[name=?]', 'role[issues_visibility]'
- end
-
- def test_edit_anonymous
- get :edit, :id => Role.anonymous.id
- assert_response :success
- assert_template 'edit'
- assert_select 'select[name=?]', 'role[issues_visibility]', 0
- end
-
- def test_edit_invalid_should_respond_with_404
- get :edit, :id => 999
- assert_response 404
- end
-
- def test_update
- put :update, :id => 1,
- :role => {:name => 'Manager',
- :permissions => ['edit_project', ''],
- :assignable => '0'}
-
- assert_redirected_to '/roles'
- role = Role.find(1)
- assert_equal [:edit_project], role.permissions
- end
-
- def test_update_with_failure
- put :update, :id => 1, :role => {:name => ''}
- assert_response :success
- assert_template 'edit'
- end
-
- def test_destroy
- r = Role.create!(:name => 'ToBeDestroyed', :permissions => [:view_wiki_pages])
-
- delete :destroy, :id => r
- assert_redirected_to '/roles'
- assert_nil Role.find_by_id(r.id)
- end
-
- def test_destroy_role_in_use
- delete :destroy, :id => 1
- assert_redirected_to '/roles'
- assert_equal 'This role is in use and cannot be deleted.', flash[:error]
- assert_not_nil Role.find_by_id(1)
- end
-
- def test_get_permissions
- get :permissions
- assert_response :success
- assert_template 'permissions'
-
- assert_not_nil assigns(:roles)
- assert_equal Role.order('builtin, position').all, assigns(:roles)
-
- assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
- :name => 'permissions[3][]',
- :value => 'add_issues',
- :checked => 'checked' }
-
- assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
- :name => 'permissions[3][]',
- :value => 'delete_issues',
- :checked => nil }
- end
-
- def test_post_permissions
- post :permissions, :permissions => { '0' => '', '1' => ['edit_issues'], '3' => ['add_issues', 'delete_issues']}
- assert_redirected_to '/roles'
-
- assert_equal [:edit_issues], Role.find(1).permissions
- assert_equal [:add_issues, :delete_issues], Role.find(3).permissions
- assert Role.find(2).permissions.empty?
- end
-
- def test_clear_all_permissions
- post :permissions, :permissions => { '0' => '' }
- assert_redirected_to '/roles'
- assert Role.find(1).permissions.empty?
- end
-
- def test_move_highest
- put :update, :id => 3, :role => {:move_to => 'highest'}
- assert_redirected_to '/roles'
- assert_equal 1, Role.find(3).position
- end
-
- def test_move_higher
- position = Role.find(3).position
- put :update, :id => 3, :role => {:move_to => 'higher'}
- assert_redirected_to '/roles'
- assert_equal position - 1, Role.find(3).position
- end
-
- def test_move_lower
- position = Role.find(2).position
- put :update, :id => 2, :role => {:move_to => 'lower'}
- assert_redirected_to '/roles'
- assert_equal position + 1, Role.find(2).position
- end
-
- def test_move_lowest
- put :update, :id => 2, :role => {:move_to => 'lowest'}
- assert_redirected_to '/roles'
- assert_equal Role.count, Role.find(2).position
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/07/07ff3aff4af2ca5266644ab7e838820cda8c8752.svn-base
--- a/.svn/pristine/07/07ff3aff4af2ca5266644ab7e838820cda8c8752.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAutoCompletesTest < ActionController::IntegrationTest
- def test_auto_completes
- assert_routing(
- { :method => 'get', :path => "/issues/auto_complete" },
- { :controller => 'auto_completes', :action => 'issues' }
- )
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/08/086f4bbd984edf33971e918b1e5330fe445e9dd7.svn-base
--- a/.svn/pristine/08/086f4bbd984edf33971e918b1e5330fe445e9dd7.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class Redmine::MenuManager::MenuHelperTest < ActionView::TestCase
-
- include Redmine::MenuManager::MenuHelper
- include ERB::Util
- fixtures :users, :members, :projects, :enabled_modules, :roles, :member_roles
-
- def setup
- setup_with_controller
- # Stub the current menu item in the controller
- def current_menu_item
- :index
- end
- end
-
- context "MenuManager#current_menu_item" do
- should "be tested"
- end
-
- context "MenuManager#render_main_menu" do
- should "be tested"
- end
-
- context "MenuManager#render_menu" do
- should "be tested"
- end
-
- context "MenuManager#menu_item_and_children" do
- should "be tested"
- end
-
- context "MenuManager#extract_node_details" do
- should "be tested"
- end
-
- def test_render_single_menu_node
- node = Redmine::MenuManager::MenuItem.new(:testing, '/test', { })
- @output_buffer = render_single_menu_node(node, 'This is a test', node.url, false)
-
- assert_select("a.testing", "This is a test")
- end
-
- def test_render_menu_node
- single_node = Redmine::MenuManager::MenuItem.new(:single_node, '/test', { })
- @output_buffer = render_menu_node(single_node, nil)
-
- assert_select("li") do
- assert_select("a.single-node", "Single node")
- end
- end
-
- def test_render_menu_node_with_nested_items
- parent_node = Redmine::MenuManager::MenuItem.new(:parent_node, '/test', { })
- parent_node << Redmine::MenuManager::MenuItem.new(:child_one_node, '/test', { })
- parent_node << Redmine::MenuManager::MenuItem.new(:child_two_node, '/test', { })
- parent_node <<
- Redmine::MenuManager::MenuItem.new(:child_three_node, '/test', { }) <<
- Redmine::MenuManager::MenuItem.new(:child_three_inner_node, '/test', { })
-
- @output_buffer = render_menu_node(parent_node, nil)
-
- assert_select("li") do
- assert_select("a.parent-node", "Parent node")
- assert_select("ul") do
- assert_select("li a.child-one-node", "Child one node")
- assert_select("li a.child-two-node", "Child two node")
- assert_select("li") do
- assert_select("a.child-three-node", "Child three node")
- assert_select("ul") do
- assert_select("li a.child-three-inner-node", "Child three inner node")
- end
- end
- end
- end
-
- end
-
- def test_render_menu_node_with_children
- User.current = User.find(2)
-
- parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
- '/test',
- {
- :children => Proc.new {|p|
- children = []
- 3.times do |time|
- children << Redmine::MenuManager::MenuItem.new("test_child_#{time}",
- {:controller => 'issues', :action => 'index'},
- {})
- end
- children
- }
- })
- @output_buffer = render_menu_node(parent_node, Project.find(1))
-
- assert_select("li") do
- assert_select("a.parent-node", "Parent node")
- assert_select("ul") do
- assert_select("li a.test-child-0", "Test child 0")
- assert_select("li a.test-child-1", "Test child 1")
- assert_select("li a.test-child-2", "Test child 2")
- end
- end
- end
-
- def test_render_menu_node_with_nested_items_and_children
- User.current = User.find(2)
-
- parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
- '/test',
- {
- :children => Proc.new {|p|
- children = []
- 3.times do |time|
- children << Redmine::MenuManager::MenuItem.new("test_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
- end
- children
- }
- })
-
- parent_node << Redmine::MenuManager::MenuItem.new(:child_node,
- '/test',
- {
- :children => Proc.new {|p|
- children = []
- 6.times do |time|
- children << Redmine::MenuManager::MenuItem.new("test_dynamic_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
- end
- children
- }
- })
-
- @output_buffer = render_menu_node(parent_node, Project.find(1))
-
- assert_select("li") do
- assert_select("a.parent-node", "Parent node")
- assert_select("ul") do
- assert_select("li a.child-node", "Child node")
- assert_select("ul") do
- assert_select("li a.test-dynamic-child-0", "Test dynamic child 0")
- assert_select("li a.test-dynamic-child-1", "Test dynamic child 1")
- assert_select("li a.test-dynamic-child-2", "Test dynamic child 2")
- assert_select("li a.test-dynamic-child-3", "Test dynamic child 3")
- assert_select("li a.test-dynamic-child-4", "Test dynamic child 4")
- assert_select("li a.test-dynamic-child-5", "Test dynamic child 5")
- end
- assert_select("li a.test-child-0", "Test child 0")
- assert_select("li a.test-child-1", "Test child 1")
- assert_select("li a.test-child-2", "Test child 2")
- end
- end
- end
-
- def test_render_menu_node_with_children_without_an_array
- parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
- '/test',
- {
- :children => Proc.new {|p| Redmine::MenuManager::MenuItem.new("test_child", "/testing", {})}
- })
-
- assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
- @output_buffer = render_menu_node(parent_node, Project.find(1))
- end
- end
-
- def test_render_menu_node_with_incorrect_children
- parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
- '/test',
- {
- :children => Proc.new {|p| ["a string"] }
- })
-
- assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
- @output_buffer = render_menu_node(parent_node, Project.find(1))
- end
-
- end
-
- def test_menu_items_for_should_yield_all_items_if_passed_a_block
- menu_name = :test_menu_items_for_should_yield_all_items_if_passed_a_block
- Redmine::MenuManager.map menu_name do |menu|
- menu.push(:a_menu, '/', { })
- menu.push(:a_menu_2, '/', { })
- menu.push(:a_menu_3, '/', { })
- end
-
- items_yielded = []
- menu_items_for(menu_name) do |item|
- items_yielded << item
- end
-
- assert_equal 3, items_yielded.size
- end
-
- def test_menu_items_for_should_return_all_items
- menu_name = :test_menu_items_for_should_return_all_items
- Redmine::MenuManager.map menu_name do |menu|
- menu.push(:a_menu, '/', { })
- menu.push(:a_menu_2, '/', { })
- menu.push(:a_menu_3, '/', { })
- end
-
- items = menu_items_for(menu_name)
- assert_equal 3, items.size
- end
-
- def test_menu_items_for_should_skip_unallowed_items_on_a_project
- menu_name = :test_menu_items_for_should_skip_unallowed_items_on_a_project
- Redmine::MenuManager.map menu_name do |menu|
- menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
- menu.push(:a_menu_2, {:controller => 'issues', :action => 'index' }, { })
- menu.push(:unallowed, {:controller => 'issues', :action => 'unallowed' }, { })
- end
-
- User.current = User.find(2)
-
- items = menu_items_for(menu_name, Project.find(1))
- assert_equal 2, items.size
- end
-
- def test_menu_items_for_should_skip_items_that_fail_the_conditions
- menu_name = :test_menu_items_for_should_skip_items_that_fail_the_conditions
- Redmine::MenuManager.map menu_name do |menu|
- menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
- menu.push(:unallowed,
- {:controller => 'issues', :action => 'index' },
- { :if => Proc.new { false }})
- end
-
- User.current = User.find(2)
-
- items = menu_items_for(menu_name, Project.find(1))
- assert_equal 1, items.size
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/08/088eae42f08379f3106075b388f036d1754d148c.svn-base
--- a/.svn/pristine/08/088eae42f08379f3106075b388f036d1754d148c.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module EnumerationsHelper
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/08/08c1f1410c30c4d18ef6cbcbd8954d1721fb044b.svn-base
--- a/.svn/pristine/08/08c1f1410c30c4d18ef6cbcbd8954d1721fb044b.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class WatchersControllerTest < ActionController::TestCase
- fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
- :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
-
- def setup
- User.current = nil
- end
-
- def test_watch_a_single_object
- @request.session[:user_id] = 3
- assert_difference('Watcher.count') do
- xhr :post, :watch, :object_type => 'issue', :object_id => '1'
- assert_response :success
- assert_include '$(".issue-1-watcher")', response.body
- end
- assert Issue.find(1).watched_by?(User.find(3))
- end
-
- def test_watch_a_collection_with_a_single_object
- @request.session[:user_id] = 3
- assert_difference('Watcher.count') do
- xhr :post, :watch, :object_type => 'issue', :object_id => ['1']
- assert_response :success
- assert_include '$(".issue-1-watcher")', response.body
- end
- assert Issue.find(1).watched_by?(User.find(3))
- end
-
- def test_watch_a_collection_with_multiple_objects
- @request.session[:user_id] = 3
- assert_difference('Watcher.count', 2) do
- xhr :post, :watch, :object_type => 'issue', :object_id => ['1', '3']
- assert_response :success
- assert_include '$(".issue-bulk-watcher")', response.body
- end
- assert Issue.find(1).watched_by?(User.find(3))
- assert Issue.find(3).watched_by?(User.find(3))
- end
-
- def test_watch_should_be_denied_without_permission
- Role.find(2).remove_permission! :view_issues
- @request.session[:user_id] = 3
- assert_no_difference('Watcher.count') do
- xhr :post, :watch, :object_type => 'issue', :object_id => '1'
- assert_response 403
- end
- end
-
- def test_watch_invalid_class_should_respond_with_404
- @request.session[:user_id] = 3
- assert_no_difference('Watcher.count') do
- xhr :post, :watch, :object_type => 'foo', :object_id => '1'
- assert_response 404
- end
- end
-
- def test_watch_invalid_object_should_respond_with_404
- @request.session[:user_id] = 3
- assert_no_difference('Watcher.count') do
- xhr :post, :watch, :object_type => 'issue', :object_id => '999'
- assert_response 404
- end
- end
-
- def test_unwatch
- @request.session[:user_id] = 3
- assert_difference('Watcher.count', -1) do
- xhr :delete, :unwatch, :object_type => 'issue', :object_id => '2'
- assert_response :success
- assert_include '$(".issue-2-watcher")', response.body
- end
- assert !Issue.find(1).watched_by?(User.find(3))
- end
-
- def test_unwatch_a_collection_with_multiple_objects
- @request.session[:user_id] = 3
- Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
- Watcher.create!(:user_id => 3, :watchable => Issue.find(3))
-
- assert_difference('Watcher.count', -2) do
- xhr :delete, :unwatch, :object_type => 'issue', :object_id => ['1', '3']
- assert_response :success
- assert_include '$(".issue-bulk-watcher")', response.body
- end
- assert !Issue.find(1).watched_by?(User.find(3))
- assert !Issue.find(3).watched_by?(User.find(3))
- end
-
- def test_new
- @request.session[:user_id] = 2
- xhr :get, :new, :object_type => 'issue', :object_id => '2'
- assert_response :success
- assert_match /ajax-modal/, response.body
- end
-
- def test_new_for_new_record_with_project_id
- @request.session[:user_id] = 2
- xhr :get, :new, :project_id => 1
- assert_response :success
- assert_equal Project.find(1), assigns(:project)
- assert_match /ajax-modal/, response.body
- end
-
- def test_new_for_new_record_with_project_identifier
- @request.session[:user_id] = 2
- xhr :get, :new, :project_id => 'ecookbook'
- assert_response :success
- assert_equal Project.find(1), assigns(:project)
- assert_match /ajax-modal/, response.body
- end
-
- def test_create
- @request.session[:user_id] = 2
- assert_difference('Watcher.count') do
- xhr :post, :create, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
- assert_response :success
- assert_match /watchers/, response.body
- assert_match /ajax-modal/, response.body
- end
- assert Issue.find(2).watched_by?(User.find(4))
- end
-
- def test_create_multiple
- @request.session[:user_id] = 2
- assert_difference('Watcher.count', 2) do
- xhr :post, :create, :object_type => 'issue', :object_id => '2', :watcher => {:user_ids => ['4', '7']}
- assert_response :success
- assert_match /watchers/, response.body
- assert_match /ajax-modal/, response.body
- end
- assert Issue.find(2).watched_by?(User.find(4))
- assert Issue.find(2).watched_by?(User.find(7))
- end
-
- def test_autocomplete_on_watchable_creation
- @request.session[:user_id] = 2
- xhr :get, :autocomplete_for_user, :q => 'mi', :project_id => 'ecookbook'
- assert_response :success
- assert_select 'input', :count => 4
- assert_select 'input[name=?][value=1]', 'watcher[user_ids][]'
- assert_select 'input[name=?][value=2]', 'watcher[user_ids][]'
- assert_select 'input[name=?][value=8]', 'watcher[user_ids][]'
- assert_select 'input[name=?][value=9]', 'watcher[user_ids][]'
- end
-
- def test_autocomplete_on_watchable_update
- @request.session[:user_id] = 2
- xhr :get, :autocomplete_for_user, :q => 'mi', :object_id => '2' , :object_type => 'issue', :project_id => 'ecookbook'
- assert_response :success
- assert_select 'input', :count => 3
- assert_select 'input[name=?][value=2]', 'watcher[user_ids][]'
- assert_select 'input[name=?][value=8]', 'watcher[user_ids][]'
- assert_select 'input[name=?][value=9]', 'watcher[user_ids][]'
-
- end
-
- def test_append
- @request.session[:user_id] = 2
- assert_no_difference 'Watcher.count' do
- xhr :post, :append, :watcher => {:user_ids => ['4', '7']}, :project_id => 'ecookbook'
- assert_response :success
- assert_include 'watchers_inputs', response.body
- assert_include 'issue[watcher_user_ids][]', response.body
- end
- end
-
- def test_remove_watcher
- @request.session[:user_id] = 2
- assert_difference('Watcher.count', -1) do
- xhr :delete, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
- assert_response :success
- assert_match /watchers/, response.body
- end
- assert !Issue.find(2).watched_by?(User.find(3))
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/09/094f0fabb02fa5ce798642abc8745a5aba89d2d9.svn-base
--- a/.svn/pristine/09/094f0fabb02fa5ce798642abc8745a5aba89d2d9.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AccountControllerOpenidTest < ActionController::TestCase
- tests AccountController
- fixtures :users, :roles
-
- def setup
- User.current = nil
- Setting.openid = '1'
- end
-
- def teardown
- Setting.openid = '0'
- end
-
- if Object.const_defined?(:OpenID)
-
- def test_login_with_openid_for_existing_user
- Setting.self_registration = '3'
- existing_user = User.new(:firstname => 'Cool',
- :lastname => 'User',
- :mail => 'user@somedomain.com',
- :identity_url => 'http://openid.example.com/good_user')
- existing_user.login = 'cool_user'
- assert existing_user.save!
-
- post :login, :openid_url => existing_user.identity_url
- assert_redirected_to '/my/page'
- end
-
- def test_login_with_invalid_openid_provider
- Setting.self_registration = '0'
- post :login, :openid_url => 'http;//openid.example.com/good_user'
- assert_redirected_to home_url
- end
-
- def test_login_with_openid_for_existing_non_active_user
- Setting.self_registration = '2'
- existing_user = User.new(:firstname => 'Cool',
- :lastname => 'User',
- :mail => 'user@somedomain.com',
- :identity_url => 'http://openid.example.com/good_user',
- :status => User::STATUS_REGISTERED)
- existing_user.login = 'cool_user'
- assert existing_user.save!
-
- post :login, :openid_url => existing_user.identity_url
- assert_redirected_to '/login'
- end
-
- def test_login_with_openid_with_new_user_created
- Setting.self_registration = '3'
- post :login, :openid_url => 'http://openid.example.com/good_user'
- assert_redirected_to '/my/account'
- user = User.find_by_login('cool_user')
- assert user
- assert_equal 'Cool', user.firstname
- assert_equal 'User', user.lastname
- end
-
- def test_login_with_openid_with_new_user_and_self_registration_off
- Setting.self_registration = '0'
- post :login, :openid_url => 'http://openid.example.com/good_user'
- assert_redirected_to home_url
- user = User.find_by_login('cool_user')
- assert_nil user
- end
-
- def test_login_with_openid_with_new_user_created_with_email_activation_should_have_a_token
- Setting.self_registration = '1'
- post :login, :openid_url => 'http://openid.example.com/good_user'
- assert_redirected_to '/login'
- user = User.find_by_login('cool_user')
- assert user
-
- token = Token.find_by_user_id_and_action(user.id, 'register')
- assert token
- end
-
- def test_login_with_openid_with_new_user_created_with_manual_activation
- Setting.self_registration = '2'
- post :login, :openid_url => 'http://openid.example.com/good_user'
- assert_redirected_to '/login'
- user = User.find_by_login('cool_user')
- assert user
- assert_equal User::STATUS_REGISTERED, user.status
- end
-
- def test_login_with_openid_with_new_user_with_conflict_should_register
- Setting.self_registration = '3'
- existing_user = User.new(:firstname => 'Cool', :lastname => 'User', :mail => 'user@somedomain.com')
- existing_user.login = 'cool_user'
- assert existing_user.save!
-
- post :login, :openid_url => 'http://openid.example.com/good_user'
- assert_response :success
- assert_template 'register'
- assert assigns(:user)
- assert_equal 'http://openid.example.com/good_user', assigns(:user)[:identity_url]
- end
-
- def test_login_with_openid_with_new_user_with_missing_information_should_register
- Setting.self_registration = '3'
-
- post :login, :openid_url => 'http://openid.example.com/good_blank_user'
- assert_response :success
- assert_template 'register'
- assert assigns(:user)
- assert_equal 'http://openid.example.com/good_blank_user', assigns(:user)[:identity_url]
-
- assert_select 'input[name=?]', 'user[login]'
- assert_select 'input[name=?]', 'user[password]'
- assert_select 'input[name=?]', 'user[password_confirmation]'
- assert_select 'input[name=?][value=?]', 'user[identity_url]', 'http://openid.example.com/good_blank_user'
- end
-
- def test_post_login_should_not_verify_token_when_using_open_id
- ActionController::Base.allow_forgery_protection = true
- AccountController.any_instance.stubs(:using_open_id?).returns(true)
- AccountController.any_instance.stubs(:authenticate_with_open_id).returns(true)
- post :login
- assert_response 200
- ensure
- ActionController::Base.allow_forgery_protection = false
- end
-
- def test_register_after_login_failure_should_not_require_user_to_enter_a_password
- Setting.self_registration = '3'
-
- assert_difference 'User.count' do
- post :register, :user => {
- :login => 'good_blank_user',
- :password => '',
- :password_confirmation => '',
- :firstname => 'Cool',
- :lastname => 'User',
- :mail => 'user@somedomain.com',
- :identity_url => 'http://openid.example.com/good_blank_user'
- }
- assert_response 302
- end
-
- user = User.first(:order => 'id DESC')
- assert_equal 'http://openid.example.com/good_blank_user', user.identity_url
- assert user.hashed_password.blank?, "Hashed password was #{user.hashed_password}"
- end
-
- def test_setting_openid_should_return_true_when_set_to_true
- assert_equal true, Setting.openid?
- end
-
- else
- puts "Skipping openid tests."
-
- def test_dummy
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/09/09d005add00d07aeb449a6c04ad00db8e1f72fbd.svn-base
--- a/.svn/pristine/09/09d005add00d07aeb449a6c04ad00db8e1f72fbd.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingMyTest < ActionController::IntegrationTest
- def test_my
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/my/account" },
- { :controller => 'my', :action => 'account' }
- )
- end
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/my/account/destroy" },
- { :controller => 'my', :action => 'destroy' }
- )
- end
- assert_routing(
- { :method => 'get', :path => "/my/page" },
- { :controller => 'my', :action => 'page' }
- )
- assert_routing(
- { :method => 'get', :path => "/my" },
- { :controller => 'my', :action => 'index' }
- )
- assert_routing(
- { :method => 'post', :path => "/my/reset_rss_key" },
- { :controller => 'my', :action => 'reset_rss_key' }
- )
- assert_routing(
- { :method => 'post', :path => "/my/reset_api_key" },
- { :controller => 'my', :action => 'reset_api_key' }
- )
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/my/password" },
- { :controller => 'my', :action => 'password' }
- )
- end
- assert_routing(
- { :method => 'get', :path => "/my/page_layout" },
- { :controller => 'my', :action => 'page_layout' }
- )
- assert_routing(
- { :method => 'post', :path => "/my/add_block" },
- { :controller => 'my', :action => 'add_block' }
- )
- assert_routing(
- { :method => 'post', :path => "/my/remove_block" },
- { :controller => 'my', :action => 'remove_block' }
- )
- assert_routing(
- { :method => 'post', :path => "/my/order_blocks" },
- { :controller => 'my', :action => 'order_blocks' }
- )
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0a/0a01ef88ba34bfc6a3c1cef8891538f7504e9b0c.svn-base
--- a/.svn/pristine/0a/0a01ef88ba34bfc6a3c1cef8891538f7504e9b0c.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module Redmine
- module I18n
- def self.included(base)
- base.extend Redmine::I18n
- end
-
- def l(*args)
- case args.size
- when 1
- ::I18n.t(*args)
- when 2
- if args.last.is_a?(Hash)
- ::I18n.t(*args)
- elsif args.last.is_a?(String)
- ::I18n.t(args.first, :value => args.last)
- else
- ::I18n.t(args.first, :count => args.last)
- end
- else
- raise "Translation string with multiple values: #{args.first}"
- end
- end
-
- def l_or_humanize(s, options={})
- k = "#{options[:prefix]}#{s}".to_sym
- ::I18n.t(k, :default => s.to_s.humanize)
- end
-
- def l_hours(hours)
- hours = hours.to_f
- l((hours < 2.0 ? :label_f_hour : :label_f_hour_plural), :value => ("%.2f" % hours.to_f))
- end
-
- def ll(lang, str, value=nil)
- ::I18n.t(str.to_s, :value => value, :locale => lang.to_s.gsub(%r{(.+)\-(.+)$}) { "#{$1}-#{$2.upcase}" })
- end
-
- def format_date(date)
- return nil unless date
- options = {}
- options[:format] = Setting.date_format unless Setting.date_format.blank?
- options[:locale] = User.current.language unless User.current.language.blank?
- ::I18n.l(date.to_date, options)
- end
-
- def format_time(time, include_date = true)
- return nil unless time
- options = {}
- options[:format] = (Setting.time_format.blank? ? :time : Setting.time_format)
- options[:locale] = User.current.language unless User.current.language.blank?
- time = time.to_time if time.is_a?(String)
- zone = User.current.time_zone
- local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)
- (include_date ? "#{format_date(local)} " : "") + ::I18n.l(local, options)
- end
-
- def day_name(day)
- ::I18n.t('date.day_names')[day % 7]
- end
-
- def day_letter(day)
- ::I18n.t('date.abbr_day_names')[day % 7].first
- end
-
- def month_name(month)
- ::I18n.t('date.month_names')[month]
- end
-
- def valid_languages
- ::I18n.available_locales
- end
-
- # Returns an array of languages names and code sorted by names, example:
- # [["Deutsch", "de"], ["English", "en"] ...]
- #
- # The result is cached to prevent from loading all translations files.
- def languages_options
- ActionController::Base.cache_store.fetch "i18n/languages_options" do
- valid_languages.map {|lang| [ll(lang.to_s, :general_lang_name), lang.to_s]}.sort {|x,y| x.first <=> y.first }
- end
- end
-
- def find_language(lang)
- @@languages_lookup = valid_languages.inject({}) {|k, v| k[v.to_s.downcase] = v; k }
- @@languages_lookup[lang.to_s.downcase]
- end
-
- def set_language_if_valid(lang)
- if l = find_language(lang)
- ::I18n.locale = l
- end
- end
-
- def current_language
- ::I18n.locale
- end
-
- # Custom backend based on I18n::Backend::Simple with the following changes:
- # * lazy loading of translation files
- # * available_locales are determined by looking at translation file names
- class Backend
- (class << self; self; end).class_eval { public :include }
-
- module Implementation
- include ::I18n::Backend::Base
-
- # Stores translations for the given locale in memory.
- # This uses a deep merge for the translations hash, so existing
- # translations will be overwritten by new ones only at the deepest
- # level of the hash.
- def store_translations(locale, data, options = {})
- locale = locale.to_sym
- translations[locale] ||= {}
- data = data.deep_symbolize_keys
- translations[locale].deep_merge!(data)
- end
-
- # Get available locales from the translations filenames
- def available_locales
- @available_locales ||= ::I18n.load_path.map {|path| File.basename(path, '.*')}.uniq.sort.map(&:to_sym)
- end
-
- # Clean up translations
- def reload!
- @translations = nil
- @available_locales = nil
- super
- end
-
- protected
-
- def init_translations(locale)
- locale = locale.to_s
- paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale}
- load_translations(paths)
- translations[locale] ||= {}
- end
-
- def translations
- @translations ||= {}
- end
-
- # Looks up a translation from the translations hash. Returns nil if
- # eiher key is nil, or locale, scope or key do not exist as a key in the
- # nested translations hash. Splits keys or scopes containing dots
- # into multiple keys, i.e.
currency.format is regarded the same as
- #
%w(currency format).
- def lookup(locale, key, scope = [], options = {})
- init_translations(locale) unless translations.key?(locale)
- keys = ::I18n.normalize_keys(locale, key, scope, options[:separator])
-
- keys.inject(translations) do |result, _key|
- _key = _key.to_sym
- return nil unless result.is_a?(Hash) && result.has_key?(_key)
- result = result[_key]
- result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
- result
- end
- end
- end
-
- include Implementation
- # Adds fallback to default locale for untranslated strings
- include ::I18n::Backend::Fallbacks
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0b/0b7befce1d7322f245834ffc9480adf8d5c60890.svn-base
--- a/.svn/pristine/0b/0b7befce1d7322f245834ffc9480adf8d5c60890.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,294 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../test_case', __FILE__)
-require 'tmpdir'
-
-class RedminePmTest::RepositorySubversionTest < RedminePmTest::TestCase
- fixtures :projects, :users, :members, :roles, :member_roles, :auth_sources
-
- SVN_BIN = Redmine::Configuration['scm_subversion_command'] || "svn"
-
- def test_anonymous_read_on_public_repo_with_permission_should_succeed
- assert_success "ls", svn_url
- end
-
- def test_anonymous_read_on_public_repo_without_permission_should_fail
- Role.anonymous.remove_permission! :browse_repository
- assert_failure "ls", svn_url
- end
-
- def test_anonymous_read_on_private_repo_should_fail
- Project.find(1).update_attribute :is_public, false
- assert_failure "ls", svn_url
- end
-
- def test_anonymous_commit_on_public_repo_should_fail
- Role.anonymous.add_permission! :commit_access
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
-
- def test_anonymous_commit_on_private_repo_should_fail
- Role.anonymous.add_permission! :commit_access
- Project.find(1).update_attribute :is_public, false
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
-
- def test_non_member_read_on_public_repo_with_permission_should_succeed
- Role.anonymous.remove_permission! :browse_repository
- with_credentials "miscuser8", "foo" do
- assert_success "ls", svn_url
- end
- end
-
- def test_non_member_read_on_public_repo_without_permission_should_fail
- Role.anonymous.remove_permission! :browse_repository
- Role.non_member.remove_permission! :browse_repository
- with_credentials "miscuser8", "foo" do
- assert_failure "ls", svn_url
- end
- end
-
- def test_non_member_read_on_private_repo_should_fail
- Project.find(1).update_attribute :is_public, false
- with_credentials "miscuser8", "foo" do
- assert_failure "ls", svn_url
- end
- end
-
- def test_non_member_commit_on_public_repo_should_fail
- Role.non_member.add_permission! :commit_access
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
-
- def test_non_member_commit_on_private_repo_should_fail
- Role.non_member.add_permission! :commit_access
- Project.find(1).update_attribute :is_public, false
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
-
- def test_member_read_on_public_repo_with_permission_should_succeed
- Role.anonymous.remove_permission! :browse_repository
- Role.non_member.remove_permission! :browse_repository
- with_credentials "dlopper", "foo" do
- assert_success "ls", svn_url
- end
- end
-
- def test_member_read_on_public_repo_without_permission_should_fail
- Role.anonymous.remove_permission! :browse_repository
- Role.non_member.remove_permission! :browse_repository
- Role.find(2).remove_permission! :browse_repository
- with_credentials "dlopper", "foo" do
- assert_failure "ls", svn_url
- end
- end
-
- def test_member_read_on_private_repo_with_permission_should_succeed
- Project.find(1).update_attribute :is_public, false
- with_credentials "dlopper", "foo" do
- assert_success "ls", svn_url
- end
- end
-
- def test_member_read_on_private_repo_without_permission_should_fail
- Role.find(2).remove_permission! :browse_repository
- Project.find(1).update_attribute :is_public, false
- with_credentials "dlopper", "foo" do
- assert_failure "ls", svn_url
- end
- end
-
- def test_member_commit_on_public_repo_with_permission_should_succeed
- Role.find(2).add_permission! :commit_access
- with_credentials "dlopper", "foo" do
- assert_success "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
- end
-
- def test_member_commit_on_public_repo_without_permission_should_fail
- Role.find(2).remove_permission! :commit_access
- with_credentials "dlopper", "foo" do
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
- end
-
- def test_member_commit_on_private_repo_with_permission_should_succeed
- Role.find(2).add_permission! :commit_access
- Project.find(1).update_attribute :is_public, false
- with_credentials "dlopper", "foo" do
- assert_success "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
- end
-
- def test_member_commit_on_private_repo_without_permission_should_fail
- Role.find(2).remove_permission! :commit_access
- Project.find(1).update_attribute :is_public, false
- with_credentials "dlopper", "foo" do
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
- end
-
- def test_invalid_credentials_should_fail
- Project.find(1).update_attribute :is_public, false
- with_credentials "dlopper", "foo" do
- assert_success "ls", svn_url
- end
- with_credentials "dlopper", "wrong" do
- assert_failure "ls", svn_url
- end
- end
-
- def test_anonymous_read_should_fail_with_login_required
- assert_success "ls", svn_url
- with_settings :login_required => '1' do
- assert_failure "ls", svn_url
- end
- end
-
- def test_authenticated_read_should_succeed_with_login_required
- with_settings :login_required => '1' do
- with_credentials "miscuser8", "foo" do
- assert_success "ls", svn_url
- end
- end
- end
-
- def test_read_on_archived_projects_should_fail
- Project.find(1).update_attribute :status, Project::STATUS_ARCHIVED
- assert_failure "ls", svn_url
- end
-
- def test_read_on_archived_private_projects_should_fail
- Project.find(1).update_attribute :status, Project::STATUS_ARCHIVED
- Project.find(1).update_attribute :is_public, false
- with_credentials "dlopper", "foo" do
- assert_failure "ls", svn_url
- end
- end
-
- def test_read_on_closed_projects_should_succeed
- Project.find(1).update_attribute :status, Project::STATUS_CLOSED
- assert_success "ls", svn_url
- end
-
- def test_read_on_closed_private_projects_should_succeed
- Project.find(1).update_attribute :status, Project::STATUS_CLOSED
- Project.find(1).update_attribute :is_public, false
- with_credentials "dlopper", "foo" do
- assert_success "ls", svn_url
- end
- end
-
- def test_commit_on_closed_projects_should_fail
- Project.find(1).update_attribute :status, Project::STATUS_CLOSED
- Role.find(2).add_permission! :commit_access
- with_credentials "dlopper", "foo" do
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
- end
-
- def test_commit_on_closed_private_projects_should_fail
- Project.find(1).update_attribute :status, Project::STATUS_CLOSED
- Project.find(1).update_attribute :is_public, false
- Role.find(2).add_permission! :commit_access
- with_credentials "dlopper", "foo" do
- assert_failure "mkdir --message Creating_a_directory", svn_url(random_filename)
- end
- end
-
- if ldap_configured?
- def test_user_with_ldap_auth_source_should_authenticate_with_ldap_credentials
- ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
- ldap_user.login = 'example1'
- ldap_user.save!
-
- with_settings :login_required => '1' do
- with_credentials "example1", "123456" do
- assert_success "ls", svn_url
- end
- end
-
- with_settings :login_required => '1' do
- with_credentials "example1", "wrong" do
- assert_failure "ls", svn_url
- end
- end
- end
- end
-
- def test_checkout
- Dir.mktmpdir do |dir|
- assert_success "checkout", svn_url, dir
- end
- end
-
- def test_read_commands
- assert_success "info", svn_url
- assert_success "ls", svn_url
- assert_success "log", svn_url
- end
-
- def test_write_commands
- Role.find(2).add_permission! :commit_access
- filename = random_filename
-
- Dir.mktmpdir do |dir|
- assert_success "checkout", svn_url, dir
- Dir.chdir(dir) do
- # creates a file in the working copy
- f = File.new(File.join(dir, filename), "w")
- f.write "test file content"
- f.close
-
- assert_success "add", filename
- with_credentials "dlopper", "foo" do
- assert_success "commit --message Committing_a_file"
- assert_success "copy --message Copying_a_file", svn_url(filename), svn_url("#{filename}_copy")
- assert_success "delete --message Deleting_a_file", svn_url(filename)
- assert_success "mkdir --message Creating_a_directory", svn_url("#{filename}_dir")
- end
- assert_success "update"
-
- # checks that the working copy was updated
- assert File.exists?(File.join(dir, "#{filename}_copy"))
- assert File.directory?(File.join(dir, "#{filename}_dir"))
- end
- end
- end
-
- def test_read_invalid_repo_should_fail
- assert_failure "ls", svn_url("invalid")
- end
-
- protected
-
- def execute(*args)
- a = [SVN_BIN, "--no-auth-cache --non-interactive"]
- a << "--username #{username}" if username
- a << "--password #{password}" if password
-
- super a, *args
- end
-
- def svn_url(path=nil)
- host = ENV['REDMINE_TEST_DAV_SERVER'] || '127.0.0.1'
- url = "http://#{host}/svn/ecookbook"
- url << "/#{path}" if path
- url
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0b/0b8a142f46ed608799d7faf6016772f4b1f09f42.svn-base
--- a/.svn/pristine/0b/0b8a142f46ed608799d7faf6016772f4b1f09f42.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAdminTest < ActionController::IntegrationTest
- def test_administration_panel
- assert_routing(
- { :method => 'get', :path => "/admin" },
- { :controller => 'admin', :action => 'index' }
- )
- assert_routing(
- { :method => 'get', :path => "/admin/projects" },
- { :controller => 'admin', :action => 'projects' }
- )
- assert_routing(
- { :method => 'get', :path => "/admin/plugins" },
- { :controller => 'admin', :action => 'plugins' }
- )
- assert_routing(
- { :method => 'get', :path => "/admin/info" },
- { :controller => 'admin', :action => 'info' }
- )
- assert_routing(
- { :method => 'get', :path => "/admin/test_email" },
- { :controller => 'admin', :action => 'test_email' }
- )
- assert_routing(
- { :method => 'post', :path => "/admin/default_configuration" },
- { :controller => 'admin', :action => 'default_configuration' }
- )
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0b/0bba8bba58df7fc70a5a93a0d2973b34736d639d.svn-base
--- a/.svn/pristine/0b/0bba8bba58df7fc70a5a93a0d2973b34736d639d.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,448 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'cgi'
-require 'redmine/scm/adapters'
-
-if RUBY_VERSION < '1.9'
- require 'iconv'
-end
-
-module Redmine
- module Scm
- module Adapters
- class AbstractAdapter #:nodoc:
-
- # raised if scm command exited with error, e.g. unknown revision.
- class ScmCommandAborted < CommandFailed; end
-
- class << self
- def client_command
- ""
- end
-
- def shell_quote_command
- if Redmine::Platform.mswin? && RUBY_PLATFORM == 'java'
- client_command
- else
- shell_quote(client_command)
- end
- end
-
- # Returns the version of the scm client
- # Eg: [1, 5, 0] or [] if unknown
- def client_version
- []
- end
-
- # Returns the version string of the scm client
- # Eg: '1.5.0' or 'Unknown version' if unknown
- def client_version_string
- v = client_version || 'Unknown version'
- v.is_a?(Array) ? v.join('.') : v.to_s
- end
-
- # Returns true if the current client version is above
- # or equals the given one
- # If option is :unknown is set to true, it will return
- # true if the client version is unknown
- def client_version_above?(v, options={})
- ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown])
- end
-
- def client_available
- true
- end
-
- def shell_quote(str)
- if Redmine::Platform.mswin?
- '"' + str.gsub(/"/, '\\"') + '"'
- else
- "'" + str.gsub(/'/, "'\"'\"'") + "'"
- end
- end
- end
-
- def initialize(url, root_url=nil, login=nil, password=nil,
- path_encoding=nil)
- @url = url
- @login = login if login && !login.empty?
- @password = (password || "") if @login
- @root_url = root_url.blank? ? retrieve_root_url : root_url
- end
-
- def adapter_name
- 'Abstract'
- end
-
- def supports_cat?
- true
- end
-
- def supports_annotate?
- respond_to?('annotate')
- end
-
- def root_url
- @root_url
- end
-
- def url
- @url
- end
-
- def path_encoding
- nil
- end
-
- # get info about the svn repository
- def info
- return nil
- end
-
- # Returns the entry identified by path and revision identifier
- # or nil if entry doesn't exist in the repository
- def entry(path=nil, identifier=nil)
- parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
- search_path = parts[0..-2].join('/')
- search_name = parts[-1]
- if search_path.blank? && search_name.blank?
- # Root entry
- Entry.new(:path => '', :kind => 'dir')
- else
- # Search for the entry in the parent directory
- es = entries(search_path, identifier)
- es ? es.detect {|e| e.name == search_name} : nil
- end
- end
-
- # Returns an Entries collection
- # or nil if the given path doesn't exist in the repository
- def entries(path=nil, identifier=nil, options={})
- return nil
- end
-
- def branches
- return nil
- end
-
- def tags
- return nil
- end
-
- def default_branch
- return nil
- end
-
- def properties(path, identifier=nil)
- return nil
- end
-
- def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
- return nil
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- return nil
- end
-
- def cat(path, identifier=nil)
- return nil
- end
-
- def with_leading_slash(path)
- path ||= ''
- (path[0,1]!="/") ? "/#{path}" : path
- end
-
- def with_trailling_slash(path)
- path ||= ''
- (path[-1,1] == "/") ? path : "#{path}/"
- end
-
- def without_leading_slash(path)
- path ||= ''
- path.gsub(%r{^/+}, '')
- end
-
- def without_trailling_slash(path)
- path ||= ''
- (path[-1,1] == "/") ? path[0..-2] : path
- end
-
- def shell_quote(str)
- self.class.shell_quote(str)
- end
-
- private
- def retrieve_root_url
- info = self.info
- info ? info.root_url : nil
- end
-
- def target(path, sq=true)
- path ||= ''
- base = path.match(/^\//) ? root_url : url
- str = "#{base}/#{path}".gsub(/[?<>\*]/, '')
- if sq
- str = shell_quote(str)
- end
- str
- end
-
- def logger
- self.class.logger
- end
-
- def shellout(cmd, options = {}, &block)
- self.class.shellout(cmd, options, &block)
- end
-
- def self.logger
- Rails.logger
- end
-
- # Path to the file where scm stderr output is logged
- # Returns nil if the log file is not writable
- def self.stderr_log_file
- if @stderr_log_file.nil?
- writable = false
- path = Redmine::Configuration['scm_stderr_log_file'].presence
- path ||= Rails.root.join("log/#{Rails.env}.scm.stderr.log").to_s
- if File.exists?(path)
- if File.file?(path) && File.writable?(path)
- writable = true
- else
- logger.warn("SCM log file (#{path}) is not writable")
- end
- else
- begin
- File.open(path, "w") {}
- writable = true
- rescue => e
- logger.warn("SCM log file (#{path}) cannot be created: #{e.message}")
- end
- end
- @stderr_log_file = writable ? path : false
- end
- @stderr_log_file || nil
- end
-
- def self.shellout(cmd, options = {}, &block)
- if logger && logger.debug?
- logger.debug "Shelling out: #{strip_credential(cmd)}"
- # Capture stderr in a log file
- if stderr_log_file
- cmd = "#{cmd} 2>>#{shell_quote(stderr_log_file)}"
- end
- end
- begin
- mode = "r+"
- IO.popen(cmd, mode) do |io|
- io.set_encoding("ASCII-8BIT") if io.respond_to?(:set_encoding)
- io.close_write unless options[:write_stdin]
- block.call(io) if block_given?
- end
- ## If scm command does not exist,
- ## Linux JRuby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException
- ## in production environment.
- # rescue Errno::ENOENT => e
- rescue Exception => e
- msg = strip_credential(e.message)
- # The command failed, log it and re-raise
- logmsg = "SCM command failed, "
- logmsg += "make sure that your SCM command (e.g. svn) is "
- logmsg += "in PATH (#{ENV['PATH']})\n"
- logmsg += "You can configure your scm commands in config/configuration.yml.\n"
- logmsg += "#{strip_credential(cmd)}\n"
- logmsg += "with: #{msg}"
- logger.error(logmsg)
- raise CommandFailed.new(msg)
- end
- end
-
- # Hides username/password in a given command
- def self.strip_credential(cmd)
- q = (Redmine::Platform.mswin? ? '"' : "'")
- cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
- end
-
- def strip_credential(cmd)
- self.class.strip_credential(cmd)
- end
-
- def scm_iconv(to, from, str)
- return nil if str.nil?
- return str if to == from
- if str.respond_to?(:force_encoding)
- str.force_encoding(from)
- begin
- str.encode(to)
- rescue Exception => err
- logger.error("failed to convert from #{from} to #{to}. #{err}")
- nil
- end
- else
- begin
- Iconv.conv(to, from, str)
- rescue Iconv::Failure => err
- logger.error("failed to convert from #{from} to #{to}. #{err}")
- nil
- end
- end
- end
-
- def parse_xml(xml)
- if RUBY_PLATFORM == 'java'
- xml = xml.sub(%r{<\?xml[^>]*\?>}, '')
- end
- ActiveSupport::XmlMini.parse(xml)
- end
- end
-
- class Entries < Array
- def sort_by_name
- dup.sort! {|x,y|
- if x.kind == y.kind
- x.name.to_s <=> y.name.to_s
- else
- x.kind <=> y.kind
- end
- }
- end
-
- def revisions
- revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact)
- end
- end
-
- class Info
- attr_accessor :root_url, :lastrev
- def initialize(attributes={})
- self.root_url = attributes[:root_url] if attributes[:root_url]
- self.lastrev = attributes[:lastrev]
- end
- end
-
- class Entry
- attr_accessor :name, :path, :kind, :size, :lastrev, :changeset
-
- def initialize(attributes={})
- self.name = attributes[:name] if attributes[:name]
- self.path = attributes[:path] if attributes[:path]
- self.kind = attributes[:kind] if attributes[:kind]
- self.size = attributes[:size].to_i if attributes[:size]
- self.lastrev = attributes[:lastrev]
- end
-
- def is_file?
- 'file' == self.kind
- end
-
- def is_dir?
- 'dir' == self.kind
- end
-
- def is_text?
- Redmine::MimeType.is_type?('text', name)
- end
-
- def author
- if changeset
- changeset.author.to_s
- elsif lastrev
- Redmine::CodesetUtil.replace_invalid_utf8(lastrev.author.to_s.split('<').first)
- end
- end
- end
-
- class Revisions < Array
- def latest
- sort {|x,y|
- unless x.time.nil? or y.time.nil?
- x.time <=> y.time
- else
- 0
- end
- }.last
- end
- end
-
- class Revision
- attr_accessor :scmid, :name, :author, :time, :message,
- :paths, :revision, :branch, :identifier,
- :parents
-
- def initialize(attributes={})
- self.identifier = attributes[:identifier]
- self.scmid = attributes[:scmid]
- self.name = attributes[:name] || self.identifier
- self.author = attributes[:author]
- self.time = attributes[:time]
- self.message = attributes[:message] || ""
- self.paths = attributes[:paths]
- self.revision = attributes[:revision]
- self.branch = attributes[:branch]
- self.parents = attributes[:parents]
- end
-
- # Returns the readable identifier.
- def format_identifier
- self.identifier.to_s
- end
-
- def ==(other)
- if other.nil?
- false
- elsif scmid.present?
- scmid == other.scmid
- elsif identifier.present?
- identifier == other.identifier
- elsif revision.present?
- revision == other.revision
- end
- end
- end
-
- class Annotate
- attr_reader :lines, :revisions
-
- def initialize
- @lines = []
- @revisions = []
- end
-
- def add_line(line, revision)
- @lines << line
- @revisions << revision
- end
-
- def content
- content = lines.join("\n")
- end
-
- def empty?
- lines.empty?
- end
- end
-
- class Branch < String
- attr_accessor :revision, :scmid
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0b/0bd8b54775e82ba1bfa004993bdb8bf956e85c99.svn-base
--- a/.svn/pristine/0b/0bd8b54775e82ba1bfa004993bdb8bf956e85c99.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-class TimeEntryQuery < Query
-
- self.queried_class = TimeEntry
-
- self.available_columns = [
- QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
- QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :default_order => 'desc', :groupable => true),
- QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
- QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true),
- QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"),
- QueryColumn.new(:comments),
- QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours"),
- ]
-
- def initialize(attributes=nil, *args)
- super attributes
- self.filters ||= {}
- add_filter('spent_on', '*') unless filters.present?
- end
-
- def initialize_available_filters
- add_available_filter "spent_on", :type => :date_past
-
- principals = []
- if project
- principals += project.principals.sort
- unless project.leaf?
- subprojects = project.descendants.visible.all
- if subprojects.any?
- add_available_filter "subproject_id",
- :type => :list_subprojects,
- :values => subprojects.collect{|s| [s.name, s.id.to_s] }
- principals += Principal.member_of(subprojects)
- end
- end
- else
- if all_projects.any?
- # members of visible projects
- principals += Principal.member_of(all_projects)
- # project filter
- project_values = []
- if User.current.logged? && User.current.memberships.any?
- project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"]
- end
- project_values += all_projects_values
- add_available_filter("project_id",
- :type => :list, :values => project_values
- ) unless project_values.empty?
- end
- end
- principals.uniq!
- principals.sort!
- users = principals.select {|p| p.is_a?(User)}
-
- users_values = []
- users_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
- users_values += users.collect{|s| [s.name, s.id.to_s] }
- add_available_filter("user_id",
- :type => :list_optional, :values => users_values
- ) unless users_values.empty?
-
- activities = (project ? project.activities : TimeEntryActivity.shared.active)
- add_available_filter("activity_id",
- :type => :list, :values => activities.map {|a| [a.name, a.id.to_s]}
- ) unless activities.empty?
-
- add_available_filter "comments", :type => :text
- add_available_filter "hours", :type => :float
-
- add_custom_fields_filters(TimeEntryCustomField)
- add_associations_custom_fields_filters :project, :issue, :user
- end
-
- def available_columns
- return @available_columns if @available_columns
- @available_columns = self.class.available_columns.dup
- @available_columns += TimeEntryCustomField.visible.all.map {|cf| QueryCustomFieldColumn.new(cf) }
- @available_columns += IssueCustomField.visible.all.map {|cf| QueryAssociationCustomFieldColumn.new(:issue, cf) }
- @available_columns
- end
-
- def default_columns_names
- @default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours]
- end
-
- def results_scope(options={})
- order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?)
-
- TimeEntry.visible.
- where(statement).
- order(order_option).
- joins(joins_for_order_statement(order_option.join(','))).
- includes(:activity)
- end
-
- def sql_for_activity_id_field(field, operator, value)
- condition_on_id = sql_for_field(field, operator, value, Enumeration.table_name, 'id')
- condition_on_parent_id = sql_for_field(field, operator, value, Enumeration.table_name, 'parent_id')
- ids = value.map(&:to_i).join(',')
- table_name = Enumeration.table_name
- if operator == '='
- "(#{table_name}.id IN (#{ids}) OR #{table_name}.parent_id IN (#{ids}))"
- else
- "(#{table_name}.id NOT IN (#{ids}) AND (#{table_name}.parent_id IS NULL OR #{table_name}.parent_id NOT IN (#{ids})))"
- end
- end
-
- # Accepts :from/:to params as shortcut filters
- def build_from_params(params)
- super
- if params[:from].present? && params[:to].present?
- add_filter('spent_on', '><', [params[:from], params[:to]])
- elsif params[:from].present?
- add_filter('spent_on', '>=', [params[:from]])
- elsif params[:to].present?
- add_filter('spent_on', '<=', [params[:to]])
- end
- self
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0c/0ca7bda81025c5f7a9ebad14d8b0c08f3a0b8176.svn-base
--- a/.svn/pristine/0c/0ca7bda81025c5f7a9ebad14d8b0c08f3a0b8176.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingSysTest < ActionController::IntegrationTest
- def test_sys
- assert_routing(
- { :method => 'get', :path => "/sys/projects" },
- { :controller => 'sys', :action => 'projects' }
- )
- assert_routing(
- { :method => 'post', :path => "/sys/projects/testid/repository" },
- { :controller => 'sys', :action => 'create_project_repository', :id => 'testid' }
- )
- assert_routing(
- { :method => 'get', :path => "/sys/fetch_changesets" },
- { :controller => 'sys', :action => 'fetch_changesets' }
- )
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0c/0cb5ab49f6fd89443044a7c2f37992f0e2874866.svn-base
--- a/.svn/pristine/0c/0cb5ab49f6fd89443044a7c2f37992f0e2874866.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-# Copyright (C) 2007 Patrick Aljord patcito@ŋmail.com
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'redmine/scm/adapters/git_adapter'
-
-class Repository::Git < Repository
- attr_protected :root_url
- validates_presence_of :url
-
- def self.human_attribute_name(attribute_key_name, *args)
- attr_name = attribute_key_name.to_s
- if attr_name == "url"
- attr_name = "path_to_repository"
- end
- super(attr_name, *args)
- end
-
- def self.scm_adapter_class
- Redmine::Scm::Adapters::GitAdapter
- end
-
- def self.scm_name
- 'Git'
- end
-
- def report_last_commit
- extra_report_last_commit
- end
-
- def extra_report_last_commit
- return false if extra_info.nil?
- v = extra_info["extra_report_last_commit"]
- return false if v.nil?
- v.to_s != '0'
- end
-
- def supports_directory_revisions?
- true
- end
-
- def supports_revision_graph?
- true
- end
-
- def repo_log_encoding
- 'UTF-8'
- end
-
- # Returns the identifier for the given git changeset
- def self.changeset_identifier(changeset)
- changeset.scmid
- end
-
- # Returns the readable identifier for the given git changeset
- def self.format_changeset_identifier(changeset)
- changeset.revision[0, 8]
- end
-
- def branches
- scm.branches
- end
-
- def tags
- scm.tags
- end
-
- def default_branch
- scm.default_branch
- rescue Exception => e
- logger.error "git: error during get default branch: #{e.message}"
- nil
- end
-
- def find_changeset_by_name(name)
- if name.present?
- changesets.where(:revision => name.to_s).first ||
- changesets.where('scmid LIKE ?', "#{name}%").first
- end
- end
-
- def entries(path=nil, identifier=nil)
- entries = scm.entries(path, identifier, :report_last_commit => extra_report_last_commit)
- load_entries_changesets(entries)
- entries
- end
-
- # With SCMs that have a sequential commit numbering,
- # such as Subversion and Mercurial,
- # Redmine is able to be clever and only fetch changesets
- # going forward from the most recent one it knows about.
- #
- # However, Git does not have a sequential commit numbering.
- #
- # In order to fetch only new adding revisions,
- # Redmine needs to save "heads".
- #
- # In Git and Mercurial, revisions are not in date order.
- # Redmine Mercurial fixed issues.
- # * Redmine Takes Too Long On Large Mercurial Repository
- # http://www.redmine.org/issues/3449
- # * Sorting for changesets might go wrong on Mercurial repos
- # http://www.redmine.org/issues/3567
- #
- # Database revision column is text, so Redmine can not sort by revision.
- # Mercurial has revision number, and revision number guarantees revision order.
- # Redmine Mercurial model stored revisions ordered by database id to database.
- # So, Redmine Mercurial model can use correct ordering revisions.
- #
- # Redmine Mercurial adapter uses "hg log -r 0:tip --limit 10"
- # to get limited revisions from old to new.
- # But, Git 1.7.3.4 does not support --reverse with -n or --skip.
- #
- # The repository can still be fully reloaded by calling #clear_changesets
- # before fetching changesets (eg. for offline resync)
- def fetch_changesets
- scm_brs = branches
- return if scm_brs.nil? || scm_brs.empty?
-
- h1 = extra_info || {}
- h = h1.dup
- repo_heads = scm_brs.map{ |br| br.scmid }
- h["heads"] ||= []
- prev_db_heads = h["heads"].dup
- if prev_db_heads.empty?
- prev_db_heads += heads_from_branches_hash
- end
- return if prev_db_heads.sort == repo_heads.sort
-
- h["db_consistent"] ||= {}
- if changesets.count == 0
- h["db_consistent"]["ordering"] = 1
- merge_extra_info(h)
- self.save
- elsif ! h["db_consistent"].has_key?("ordering")
- h["db_consistent"]["ordering"] = 0
- merge_extra_info(h)
- self.save
- end
- save_revisions(prev_db_heads, repo_heads)
- end
-
- def save_revisions(prev_db_heads, repo_heads)
- h = {}
- opts = {}
- opts[:reverse] = true
- opts[:excludes] = prev_db_heads
- opts[:includes] = repo_heads
-
- revisions = scm.revisions('', nil, nil, opts)
- return if revisions.blank?
-
- # Make the search for existing revisions in the database in a more sufficient manner
- #
- # Git branch is the reference to the specific revision.
- # Git can *delete* remote branch and *re-push* branch.
- #
- # $ git push remote :branch
- # $ git push remote branch
- #
- # After deleting branch, revisions remain in repository until "git gc".
- # On git 1.7.2.3, default pruning date is 2 weeks.
- # So, "git log --not deleted_branch_head_revision" return code is 0.
- #
- # After re-pushing branch, "git log" returns revisions which are saved in database.
- # So, Redmine needs to scan revisions and database every time.
- #
- # This is replacing the one-after-one queries.
- # Find all revisions, that are in the database, and then remove them from the revision array.
- # Then later we won't need any conditions for db existence.
- # Query for several revisions at once, and remove them from the revisions array, if they are there.
- # Do this in chunks, to avoid eventual memory problems (in case of tens of thousands of commits).
- # If there are no revisions (because the original code's algorithm filtered them),
- # then this part will be stepped over.
- # We make queries, just if there is any revision.
- limit = 100
- offset = 0
- revisions_copy = revisions.clone # revisions will change
- while offset < revisions_copy.size
- scmids = revisions_copy.slice(offset, limit).map{|x| x.scmid}
- recent_changesets_slice = changesets.where(:scmid => scmids).all
- # Subtract revisions that redmine already knows about
- recent_revisions = recent_changesets_slice.map{|c| c.scmid}
- revisions.reject!{|r| recent_revisions.include?(r.scmid)}
- offset += limit
- end
-
- revisions.each do |rev|
- transaction do
- # There is no search in the db for this revision, because above we ensured,
- # that it's not in the db.
- save_revision(rev)
- end
- end
- h["heads"] = repo_heads.dup
- merge_extra_info(h)
- self.save
- end
- private :save_revisions
-
- def save_revision(rev)
- parents = (rev.parents || []).collect{|rp| find_changeset_by_name(rp)}.compact
- changeset = Changeset.create(
- :repository => self,
- :revision => rev.identifier,
- :scmid => rev.scmid,
- :committer => rev.author,
- :committed_on => rev.time,
- :comments => rev.message,
- :parents => parents
- )
- unless changeset.new_record?
- rev.paths.each { |change| changeset.create_change(change) }
- end
- changeset
- end
- private :save_revision
-
- def heads_from_branches_hash
- h1 = extra_info || {}
- h = h1.dup
- h["branches"] ||= {}
- h['branches'].map{|br, hs| hs['last_scmid']}
- end
-
- def latest_changesets(path,rev,limit=10)
- revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false)
- return [] if revisions.nil? || revisions.empty?
-
- changesets.where(:scmid => revisions.map {|c| c.scmid}).all
- end
-
- def clear_extra_info_of_changesets
- return if extra_info.nil?
- v = extra_info["extra_report_last_commit"]
- write_attribute(:extra_info, nil)
- h = {}
- h["extra_report_last_commit"] = v
- merge_extra_info(h)
- self.save
- end
- private :clear_extra_info_of_changesets
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0c/0cc9601ec1a6e3a27ab4a946d394cf4ba82254b4.svn-base
--- a/.svn/pristine/0c/0cc9601ec1a6e3a27ab4a946d394cf4ba82254b4.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-class TimeEntryActivityCustomField < CustomField
- def type_name
- :enumeration_activities
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0e/0e9c8f11b3db41702079f085c94dfa01133abcd9.svn-base
--- a/.svn/pristine/0e/0e9c8f11b3db41702079f085c94dfa01133abcd9.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../../../test_helper', __FILE__)
-
-class PdfTest < ActiveSupport::TestCase
- fixtures :users, :projects, :roles, :members, :member_roles,
- :enabled_modules, :issues, :trackers, :attachments
-
- def test_fix_text_encoding_nil
- assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(nil, "UTF-8")
- assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(nil, "ISO-8859-1")
- end
-
- def test_rdm_pdf_iconv_cannot_convert_ja_cp932
- encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
- utf8_txt_1 = "\xe7\x8b\x80\xe6\x85\x8b"
- utf8_txt_2 = "\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
- utf8_txt_3 = "\xe7\x8b\x80\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
- if utf8_txt_1.respond_to?(:force_encoding)
- txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
- txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
- txt_3 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
- assert_equal "?\x91\xd4".force_encoding("ASCII-8BIT"), txt_1
- assert_equal "?\x91\xd4?".force_encoding("ASCII-8BIT"), txt_2
- assert_equal "??\x91\xd4?".force_encoding("ASCII-8BIT"), txt_3
- assert_equal "ASCII-8BIT", txt_1.encoding.to_s
- assert_equal "ASCII-8BIT", txt_2.encoding.to_s
- assert_equal "ASCII-8BIT", txt_3.encoding.to_s
- elsif RUBY_PLATFORM == 'java'
- assert_equal "??",
- Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
- assert_equal "???",
- Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
- assert_equal "????",
- Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
- else
- assert_equal "???\x91\xd4",
- Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
- assert_equal "???\x91\xd4???",
- Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
- assert_equal "??????\x91\xd4???",
- Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
- end
- end
-
- def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_en
- str1 = "Texte encod\xe9 en ISO-8859-1"
- str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
- str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
- str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
- txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, 'UTF-8')
- txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, 'UTF-8')
- if txt_1.respond_to?(:force_encoding)
- assert_equal "ASCII-8BIT", txt_1.encoding.to_s
- assert_equal "ASCII-8BIT", txt_2.encoding.to_s
- end
- assert_equal "Texte encod? en ISO-8859-1", txt_1
- assert_equal "?a?b?c?d?e test", txt_2
- end
-
- def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja
- str1 = "Texte encod\xe9 en ISO-8859-1"
- str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
- str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
- str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
- encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
- txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, encoding)
- txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, encoding)
- if txt_1.respond_to?(:force_encoding)
- assert_equal "ASCII-8BIT", txt_1.encoding.to_s
- assert_equal "ASCII-8BIT", txt_2.encoding.to_s
- end
- assert_equal "Texte encod? en ISO-8859-1", txt_1
- assert_equal "?a?b?c?d?e test", txt_2
- end
-
- def test_attach
- set_fixtures_attachments_directory
-
- str2 = "\x83e\x83X\x83g"
- str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
- encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
-
- a1 = Attachment.find(17)
- a2 = Attachment.find(19)
-
- User.current = User.find(1)
- assert a1.readable?
- assert a1.visible?
- assert a2.readable?
- assert a2.visible?
-
- aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
- assert_not_nil aa1
- assert_equal 17, aa1.id
- aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
- assert_not_nil aa2
- assert_equal 19, aa2.id
-
- User.current = nil
- assert a1.readable?
- assert (! a1.visible?)
- assert a2.readable?
- assert (! a2.visible?)
-
- aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
- assert_equal nil, aa1
- aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
- assert_equal nil, aa2
-
- set_tmp_attachments_directory
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/0f/0fc81c2978046c22ad1fddeadeabe4e288474193.svn-base
--- a/.svn/pristine/0f/0fc81c2978046c22ad1fddeadeabe4e288474193.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesBazaarControllerTest < ActionController::TestCase
- tests RepositoriesController
-
- fixtures :projects, :users, :roles, :members, :member_roles,
- :repositories, :enabled_modules
-
- REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
- REPOSITORY_PATH_TRUNK = File.join(REPOSITORY_PATH, "trunk")
- PRJ_ID = 3
- CHAR_1_UTF8_HEX = "\xc3\x9c"
-
- def setup
- User.current = nil
- @project = Project.find(PRJ_ID)
- @repository = Repository::Bazaar.create(
- :project => @project,
- :url => REPOSITORY_PATH_TRUNK,
- :log_encoding => 'UTF-8')
- assert @repository
- @char_1_utf8 = CHAR_1_UTF8_HEX.dup
- if @char_1_utf8.respond_to?(:force_encoding)
- @char_1_utf8.force_encoding('UTF-8')
- end
- end
-
- if File.directory?(REPOSITORY_PATH)
- def test_get_new
- @request.session[:user_id] = 1
- @project.repository.destroy
- get :new, :project_id => 'subproject1', :repository_scm => 'Bazaar'
- assert_response :success
- assert_template 'new'
- assert_kind_of Repository::Bazaar, assigns(:repository)
- assert assigns(:repository).new_record?
- end
-
- def test_browse_root
- get :show, :id => PRJ_ID
- assert_response :success
- assert_template 'show'
- assert_not_nil assigns(:entries)
- assert_equal 2, assigns(:entries).size
- assert assigns(:entries).detect {|e| e.name == 'directory' && e.kind == 'dir'}
- assert assigns(:entries).detect {|e| e.name == 'doc-mkdir.txt' && e.kind == 'file'}
- end
-
- def test_browse_directory
- get :show, :id => PRJ_ID, :path => repository_path_hash(['directory'])[:param]
- assert_response :success
- assert_template 'show'
- assert_not_nil assigns(:entries)
- assert_equal ['doc-ls.txt', 'document.txt', 'edit.png'], assigns(:entries).collect(&:name)
- entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
- assert_not_nil entry
- assert_equal 'file', entry.kind
- assert_equal 'directory/edit.png', entry.path
- end
-
- def test_browse_at_given_revision
- get :show, :id => PRJ_ID, :path => repository_path_hash([])[:param],
- :rev => 3
- assert_response :success
- assert_template 'show'
- assert_not_nil assigns(:entries)
- assert_equal ['directory', 'doc-deleted.txt', 'doc-ls.txt', 'doc-mkdir.txt'],
- assigns(:entries).collect(&:name)
- end
-
- def test_changes
- get :changes, :id => PRJ_ID,
- :path => repository_path_hash(['doc-mkdir.txt'])[:param]
- assert_response :success
- assert_template 'changes'
- assert_tag :tag => 'h2', :content => 'doc-mkdir.txt'
- end
-
- def test_entry_show
- get :entry, :id => PRJ_ID,
- :path => repository_path_hash(['directory', 'doc-ls.txt'])[:param]
- assert_response :success
- assert_template 'entry'
- # Line 19
- assert_tag :tag => 'th',
- :content => /29/,
- :attributes => { :class => /line-num/ },
- :sibling => { :tag => 'td', :content => /Show help message/ }
- end
-
- def test_entry_download
- get :entry, :id => PRJ_ID,
- :path => repository_path_hash(['directory', 'doc-ls.txt'])[:param],
- :format => 'raw'
- assert_response :success
- # File content
- assert @response.body.include?('Show help message')
- end
-
- def test_directory_entry
- get :entry, :id => PRJ_ID,
- :path => repository_path_hash(['directory'])[:param]
- assert_response :success
- assert_template 'show'
- assert_not_nil assigns(:entry)
- assert_equal 'directory', assigns(:entry).name
- end
-
- def test_diff
- # Full diff of changeset 3
- ['inline', 'sbs'].each do |dt|
- get :diff, :id => PRJ_ID, :rev => 3, :type => dt
- assert_response :success
- assert_template 'diff'
- # Line 11 removed
- assert_tag :tag => 'th',
- :content => '11',
- :sibling => { :tag => 'td',
- :attributes => { :class => /diff_out/ },
- :content => /Display more information/ }
- end
- end
-
- def test_annotate
- get :annotate, :id => PRJ_ID,
- :path => repository_path_hash(['doc-mkdir.txt'])[:param]
- assert_response :success
- assert_template 'annotate'
- assert_select "th.line-num", :text => '2' do
- assert_select "+ td.revision" do
- assert_select "a", :text => '3'
- assert_select "+ td.author", :text => "jsmith@" do
- assert_select "+ td",
- :text => "Main purpose:"
- end
- end
- end
- end
-
- def test_annotate_author_escaping
- repository = Repository::Bazaar.create(
- :project => @project,
- :url => File.join(REPOSITORY_PATH, "author_escaping"),
- :identifier => 'author_escaping',
- :log_encoding => 'UTF-8')
- assert repository
- get :annotate, :id => PRJ_ID, :repository_id => 'author_escaping',
- :path => repository_path_hash(['author-escaping-test.txt'])[:param]
- assert_response :success
- assert_template 'annotate'
- assert_select "th.line-num", :text => '1' do
- assert_select "+ td.revision" do
- assert_select "a", :text => '2'
- assert_select "+ td.author", :text => "test &" do
- assert_select "+ td",
- :text => "author escaping test"
- end
- end
- end
- end
-
- if REPOSITORY_PATH.respond_to?(:force_encoding)
- def test_annotate_author_non_ascii
- log_encoding = nil
- if Encoding.locale_charmap == "UTF-8" ||
- Encoding.locale_charmap == "ISO-8859-1"
- log_encoding = Encoding.locale_charmap
- end
- unless log_encoding.nil?
- repository = Repository::Bazaar.create(
- :project => @project,
- :url => File.join(REPOSITORY_PATH, "author_non_ascii"),
- :identifier => 'author_non_ascii',
- :log_encoding => log_encoding)
- assert repository
- get :annotate, :id => PRJ_ID, :repository_id => 'author_non_ascii',
- :path => repository_path_hash(['author-non-ascii-test.txt'])[:param]
- assert_response :success
- assert_template 'annotate'
- assert_select "th.line-num", :text => '1' do
- assert_select "+ td.revision" do
- assert_select "a", :text => '2'
- assert_select "+ td.author", :text => "test #{@char_1_utf8}" do
- assert_select "+ td",
- :text => "author non ASCII test"
- end
- end
- end
- end
- end
- end
-
- def test_destroy_valid_repository
- @request.session[:user_id] = 1 # admin
- assert_equal 0, @repository.changesets.count
- @repository.fetch_changesets
- assert @repository.changesets.count > 0
-
- assert_difference 'Repository.count', -1 do
- delete :destroy, :id => @repository.id
- end
- assert_response 302
- @project.reload
- assert_nil @project.repository
- end
-
- def test_destroy_invalid_repository
- @request.session[:user_id] = 1 # admin
- @project.repository.destroy
- @repository = Repository::Bazaar.create!(
- :project => @project,
- :url => "/invalid",
- :log_encoding => 'UTF-8')
- @repository.fetch_changesets
- @repository.reload
- assert_equal 0, @repository.changesets.count
-
- assert_difference 'Repository.count', -1 do
- delete :destroy, :id => @repository.id
- end
- assert_response 302
- @project.reload
- assert_nil @project.repository
- end
- else
- puts "Bazaar test repository NOT FOUND. Skipping functional tests !!!"
- def test_fake; assert true end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/11/11276ad92ab446760ef27dc63e4ad98666e8240c.svn-base
--- a/.svn/pristine/11/11276ad92ab446760ef27dc63e4ad98666e8240c.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingAccountTest < ActionController::IntegrationTest
- def test_account
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/login" },
- { :controller => 'account', :action => 'login' }
- )
- end
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/logout" },
- { :controller => 'account', :action => 'logout' }
- )
- end
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/account/register" },
- { :controller => 'account', :action => 'register' }
- )
- end
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/account/lost_password" },
- { :controller => 'account', :action => 'lost_password' }
- )
- end
- assert_routing(
- { :method => 'get', :path => "/account/activate" },
- { :controller => 'account', :action => 'activate' }
- )
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/11/11c16631f55588a98678a93f0bb375404c2e534c.svn-base
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/11/11c16631f55588a98678a93f0bb375404c2e534c.svn-base Tue Sep 09 09:28:31 2014 +0100
@@ -0,0 +1,33 @@
+# Settings specified here will take precedence over those in config/application.rb
+RedmineApp::Application.configure do
+ # The production environment is meant for finished, "live" apps.
+ # Code is not reloaded between requests
+ config.cache_classes = true
+
+ #####
+ # Customize the default logger
+ # http://www.ruby-doc.org/stdlib-1.8.7/libdoc/logger/rdoc/Logger.html
+ #
+ # Use a different logger for distributed setups
+ # config.logger = SyslogLogger.new
+ #
+ # Rotate logs bigger than 1MB, keeps no more than 7 rotated logs around.
+ # When setting a new Logger, make sure to set it's log level too.
+ #
+ # config.logger = Logger.new(config.log_path, 7, 1048576)
+ # config.logger.level = Logger::INFO
+
+ # Full error reports are disabled and caching is turned on
+ config.action_controller.perform_caching = true
+
+ # Enable serving of images, stylesheets, and javascripts from an asset server
+ # config.action_controller.asset_host = "http://assets.example.com"
+
+ # Disable delivery errors if you bad email addresses should just be ignored
+ config.action_mailer.raise_delivery_errors = false
+
+ # No email in production log
+ config.action_mailer.logger = nil
+
+ config.active_support.deprecation = :log
+end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/12/120840d537ad68f417065b102e2763e8f985fe62.svn-base
--- a/.svn/pristine/12/120840d537ad68f417065b102e2763e8f985fe62.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-class MembersController < ApplicationController
- model_object Member
- before_filter :find_model_object, :except => [:index, :create, :autocomplete]
- before_filter :find_project_from_association, :except => [:index, :create, :autocomplete]
- before_filter :find_project_by_project_id, :only => [:index, :create, :autocomplete]
- before_filter :authorize
- accept_api_auth :index, :show, :create, :update, :destroy
-
- def index
- @offset, @limit = api_offset_and_limit
- @member_count = @project.member_principals.count
- @member_pages = Paginator.new @member_count, @limit, params['page']
- @offset ||= @member_pages.offset
- @members = @project.member_principals.all(
- :order => "#{Member.table_name}.id",
- :limit => @limit,
- :offset => @offset
- )
-
- respond_to do |format|
- format.html { head 406 }
- format.api
- end
- end
-
- def show
- respond_to do |format|
- format.html { head 406 }
- format.api
- end
- end
-
- def create
- members = []
- if params[:membership]
- if params[:membership][:user_ids]
- attrs = params[:membership].dup
- user_ids = attrs.delete(:user_ids)
- user_ids.each do |user_id|
- members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id)
- end
- else
- members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => params[:membership][:user_id])
- end
- @project.members << members
- end
-
- respond_to do |format|
- format.html { redirect_to_settings_in_projects }
- format.js { @members = members }
- format.api {
- @member = members.first
- if @member.valid?
- render :action => 'show', :status => :created, :location => membership_url(@member)
- else
- render_validation_errors(@member)
- end
- }
- end
- end
-
- def update
- if params[:membership]
- @member.role_ids = params[:membership][:role_ids]
- end
- saved = @member.save
- respond_to do |format|
- format.html { redirect_to_settings_in_projects }
- format.js
- format.api {
- if saved
- render_api_ok
- else
- render_validation_errors(@member)
- end
- }
- end
- end
-
- def destroy
- if request.delete? && @member.deletable?
- @member.destroy
- end
- respond_to do |format|
- format.html { redirect_to_settings_in_projects }
- format.js
- format.api {
- if @member.destroyed?
- render_api_ok
- else
- head :unprocessable_entity
- end
- }
- end
- end
-
- def autocomplete
- respond_to do |format|
- format.js
- end
- end
-
- private
-
- def redirect_to_settings_in_projects
- redirect_to settings_project_path(@project, :tab => 'members')
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/13/134ab6c377c7865f7eab83c298719a41c97ec009.svn-base
--- a/.svn/pristine/13/134ab6c377c7865f7eab83c298719a41c97ec009.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class AttachmentsTest < ActionController::IntegrationTest
- fixtures :projects, :enabled_modules,
- :users, :roles, :members, :member_roles,
- :trackers, :projects_trackers,
- :issue_statuses, :enumerations
-
- def test_upload_as_js_and_attach_to_an_issue
- log_user('jsmith', 'jsmith')
-
- token = ajax_upload('myupload.txt', 'File content')
-
- assert_difference 'Issue.count' do
- post '/projects/ecookbook/issues', {
- :issue => {:tracker_id => 1, :subject => 'Issue with upload'},
- :attachments => {'1' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
- }
- assert_response 302
- end
-
- issue = Issue.order('id DESC').first
- assert_equal 'Issue with upload', issue.subject
- assert_equal 1, issue.attachments.count
-
- attachment = issue.attachments.first
- assert_equal 'myupload.txt', attachment.filename
- assert_equal 'My uploaded file', attachment.description
- assert_equal 'File content'.length, attachment.filesize
- end
-
- def test_upload_as_js_and_preview_as_inline_attachment
- log_user('jsmith', 'jsmith')
-
- token = ajax_upload('myupload.jpg', 'JPEG content')
-
- post '/issues/preview/new/ecookbook', {
- :issue => {:tracker_id => 1, :description => 'Inline upload: !myupload.jpg!'},
- :attachments => {'1' => {:filename => 'myupload.jpg', :description => 'My uploaded file', :token => token}}
- }
- assert_response :success
-
- attachment_path = response.body.match(%r{
)
{:tracker_id => 1, :subject => ''},
- :attachments => {'1' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
- }
- assert_response :success
- end
- assert_select 'input[type=hidden][name=?][value=?]', 'attachments[p0][token]', token
- assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'myupload.txt'
- assert_select 'input[name=?][value=?]', 'attachments[p0][description]', 'My uploaded file'
-
- assert_difference 'Issue.count' do
- post '/projects/ecookbook/issues', {
- :issue => {:tracker_id => 1, :subject => 'Issue with upload'},
- :attachments => {'p0' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
- }
- assert_response 302
- end
-
- issue = Issue.order('id DESC').first
- assert_equal 'Issue with upload', issue.subject
- assert_equal 1, issue.attachments.count
-
- attachment = issue.attachments.first
- assert_equal 'myupload.txt', attachment.filename
- assert_equal 'My uploaded file', attachment.description
- assert_equal 'File content'.length, attachment.filesize
- end
-
- def test_upload_as_js_and_destroy
- log_user('jsmith', 'jsmith')
-
- token = ajax_upload('myupload.txt', 'File content')
-
- attachment = Attachment.order('id DESC').first
- attachment_path = "/attachments/#{attachment.id}.js?attachment_id=1"
- assert_include "href: '#{attachment_path}'", response.body, "Path to attachment: #{attachment_path} not found in response:\n#{response.body}"
-
- assert_difference 'Attachment.count', -1 do
- delete attachment_path
- assert_response :success
- end
-
- assert_include "$('#attachments_1').remove();", response.body
- end
-
- private
-
- def ajax_upload(filename, content, attachment_id=1)
- assert_difference 'Attachment.count' do
- post "/uploads.js?attachment_id=#{attachment_id}&filename=#{filename}", content, {"CONTENT_TYPE" => 'application/octet-stream'}
- assert_response :success
- assert_equal 'text/javascript', response.content_type
- end
-
- token = response.body.match(/\.val\('(\d+\.[0-9a-f]+)'\)/)[1]
- assert_not_nil token, "No upload token found in response:\n#{response.body}"
- token
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/13/1398acbd60647babc95a74c09ce2afa2acef1b0b.svn-base
--- a/.svn/pristine/13/1398acbd60647babc95a74c09ce2afa2acef1b0b.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../../../../test_helper', __FILE__)
-
-class Redmine::Views::Builders::JsonTest < ActiveSupport::TestCase
-
- def test_hash
- assert_json_output({'person' => {'name' => 'Ryan', 'age' => 32}}) do |b|
- b.person do
- b.name 'Ryan'
- b.age 32
- end
- end
- end
-
- def test_hash_hash
- assert_json_output({'person' => {'name' => 'Ryan', 'birth' => {'city' => 'London', 'country' => 'UK'}}}) do |b|
- b.person do
- b.name 'Ryan'
- b.birth :city => 'London', :country => 'UK'
- end
- end
-
- assert_json_output({'person' => {'id' => 1, 'name' => 'Ryan', 'birth' => {'city' => 'London', 'country' => 'UK'}}}) do |b|
- b.person :id => 1 do
- b.name 'Ryan'
- b.birth :city => 'London', :country => 'UK'
- end
- end
- end
-
- def test_array
- assert_json_output({'books' => [{'title' => 'Book 1', 'author' => 'B. Smith'}, {'title' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
- b.array :books do |b|
- b.book :title => 'Book 1', :author => 'B. Smith'
- b.book :title => 'Book 2', :author => 'G. Cooper'
- end
- end
-
- assert_json_output({'books' => [{'title' => 'Book 1', 'author' => 'B. Smith'}, {'title' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
- b.array :books do |b|
- b.book :title => 'Book 1' do
- b.author 'B. Smith'
- end
- b.book :title => 'Book 2' do
- b.author 'G. Cooper'
- end
- end
- end
- end
-
- def test_array_with_content_tags
- assert_json_output({'books' => [{'value' => 'Book 1', 'author' => 'B. Smith'}, {'value' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
- b.array :books do |b|
- b.book 'Book 1', :author => 'B. Smith'
- b.book 'Book 2', :author => 'G. Cooper'
- end
- end
- end
-
- def test_nested_arrays
- assert_json_output({'books' => [{'authors' => ['B. Smith', 'G. Cooper']}]}) do |b|
- b.array :books do |books|
- books.book do |book|
- book.array :authors do |authors|
- authors.author 'B. Smith'
- authors.author 'G. Cooper'
- end
- end
- end
- end
- end
-
- def assert_json_output(expected, &block)
- builder = Redmine::Views::Builders::Json.new(ActionDispatch::TestRequest.new, ActionDispatch::TestResponse.new)
- block.call(builder)
- assert_equal(expected, ActiveSupport::JSON.decode(builder.output))
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/13/13e6190365f9e0ad8532e5e563cf7ad5676797a5.svn-base
--- a/.svn/pristine/13/13e6190365f9e0ad8532e5e563cf7ad5676797a5.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1044 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-class Project < ActiveRecord::Base
- include Redmine::SafeAttributes
-
- # Project statuses
- STATUS_ACTIVE = 1
- STATUS_CLOSED = 5
- STATUS_ARCHIVED = 9
-
- # Maximum length for project identifiers
- IDENTIFIER_MAX_LENGTH = 100
-
- # Specific overidden Activities
- has_many :time_entry_activities
- has_many :members, :include => [:principal, :roles], :conditions => "#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}"
- has_many :memberships, :class_name => 'Member'
- has_many :member_principals, :class_name => 'Member',
- :include => :principal,
- :conditions => "#{Principal.table_name}.type='Group' OR (#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE})"
-
- has_many :enabled_modules, :dependent => :delete_all
- has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
- has_many :issues, :dependent => :destroy, :include => [:status, :tracker]
- has_many :issue_changes, :through => :issues, :source => :journals
- has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
- has_many :time_entries, :dependent => :delete_all
- has_many :queries, :class_name => 'IssueQuery', :dependent => :delete_all
- has_many :documents, :dependent => :destroy
- has_many :news, :dependent => :destroy, :include => :author
- has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
- has_many :boards, :dependent => :destroy, :order => "position ASC"
- has_one :repository, :conditions => ["is_default = ?", true]
- has_many :repositories, :dependent => :destroy
- has_many :changesets, :through => :repository
- has_one :wiki, :dependent => :destroy
- # Custom field for the project issues
- has_and_belongs_to_many :issue_custom_fields,
- :class_name => 'IssueCustomField',
- :order => "#{CustomField.table_name}.position",
- :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
- :association_foreign_key => 'custom_field_id'
-
- acts_as_nested_set :order => 'name', :dependent => :destroy
- acts_as_attachable :view_permission => :view_files,
- :delete_permission => :manage_files
-
- acts_as_customizable
- acts_as_searchable :columns => ['name', 'identifier', 'description'], :project_key => 'id', :permission => nil
- acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
- :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}},
- :author => nil
-
- attr_protected :status
-
- validates_presence_of :name, :identifier
- validates_uniqueness_of :identifier
- validates_associated :repository, :wiki
- validates_length_of :name, :maximum => 255
- validates_length_of :homepage, :maximum => 255
- validates_length_of :identifier, :in => 1..IDENTIFIER_MAX_LENGTH
- # donwcase letters, digits, dashes but not digits only
- validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :if => Proc.new { |p| p.identifier_changed? }
- # reserved words
- validates_exclusion_of :identifier, :in => %w( new )
-
- after_save :update_position_under_parent, :if => Proc.new {|project| project.name_changed?}
- after_save :update_inherited_members, :if => Proc.new {|project| project.inherit_members_changed?}
- before_destroy :delete_all_members
-
- scope :has_module, lambda {|mod|
- where("#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s)
- }
- scope :active, lambda { where(:status => STATUS_ACTIVE) }
- scope :status, lambda {|arg| where(arg.blank? ? nil : {:status => arg.to_i}) }
- scope :all_public, lambda { where(:is_public => true) }
- scope :visible, lambda {|*args| where(Project.visible_condition(args.shift || User.current, *args)) }
- scope :allowed_to, lambda {|*args|
- user = User.current
- permission = nil
- if args.first.is_a?(Symbol)
- permission = args.shift
- else
- user = args.shift
- permission = args.shift
- end
- where(Project.allowed_to_condition(user, permission, *args))
- }
- scope :like, lambda {|arg|
- if arg.blank?
- where(nil)
- else
- pattern = "%#{arg.to_s.strip.downcase}%"
- where("LOWER(identifier) LIKE :p OR LOWER(name) LIKE :p", :p => pattern)
- end
- }
-
- def initialize(attributes=nil, *args)
- super
-
- initialized = (attributes || {}).stringify_keys
- if !initialized.key?('identifier') && Setting.sequential_project_identifiers?
- self.identifier = Project.next_identifier
- end
- if !initialized.key?('is_public')
- self.is_public = Setting.default_projects_public?
- end
- if !initialized.key?('enabled_module_names')
- self.enabled_module_names = Setting.default_projects_modules
- end
- if !initialized.key?('trackers') && !initialized.key?('tracker_ids')
- default = Setting.default_projects_tracker_ids
- if default.is_a?(Array)
- self.trackers = Tracker.where(:id => default.map(&:to_i)).sorted.all
- else
- self.trackers = Tracker.sorted.all
- end
- end
- end
-
- def identifier=(identifier)
- super unless identifier_frozen?
- end
-
- def identifier_frozen?
- errors[:identifier].blank? && !(new_record? || identifier.blank?)
- end
-
- # returns latest created projects
- # non public projects will be returned only if user is a member of those
- def self.latest(user=nil, count=5)
- visible(user).limit(count).order("created_on DESC").all
- end
-
- # Returns true if the project is visible to +user+ or to the current user.
- def visible?(user=User.current)
- user.allowed_to?(:view_project, self)
- end
-
- # Returns a SQL conditions string used to find all projects visible by the specified user.
- #
- # Examples:
- # Project.visible_condition(admin) => "projects.status = 1"
- # Project.visible_condition(normal_user) => "((projects.status = 1) AND (projects.is_public = 1 OR projects.id IN (1,3,4)))"
- # Project.visible_condition(anonymous) => "((projects.status = 1) AND (projects.is_public = 1))"
- def self.visible_condition(user, options={})
- allowed_to_condition(user, :view_project, options)
- end
-
- # Returns a SQL conditions string used to find all projects for which +user+ has the given +permission+
- #
- # Valid options:
- # * :project => limit the condition to project
- # * :with_subprojects => limit the condition to project and its subprojects
- # * :member => limit the condition to the user projects
- def self.allowed_to_condition(user, permission, options={})
- perm = Redmine::AccessControl.permission(permission)
- base_statement = (perm && perm.read? ? "#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED}" : "#{Project.table_name}.status = #{Project::STATUS_ACTIVE}")
- if perm && perm.project_module
- # If the permission belongs to a project module, make sure the module is enabled
- base_statement << " AND #{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name='#{perm.project_module}')"
- end
- if options[:project]
- project_statement = "#{Project.table_name}.id = #{options[:project].id}"
- project_statement << " OR (#{Project.table_name}.lft > #{options[:project].lft} AND #{Project.table_name}.rgt < #{options[:project].rgt})" if options[:with_subprojects]
- base_statement = "(#{project_statement}) AND (#{base_statement})"
- end
-
- if user.admin?
- base_statement
- else
- statement_by_role = {}
- unless options[:member]
- role = user.builtin_role
- if role.allowed_to?(permission)
- statement_by_role[role] = "#{Project.table_name}.is_public = #{connection.quoted_true}"
- end
- end
- if user.logged?
- user.projects_by_role.each do |role, projects|
- if role.allowed_to?(permission) && projects.any?
- statement_by_role[role] = "#{Project.table_name}.id IN (#{projects.collect(&:id).join(',')})"
- end
- end
- end
- if statement_by_role.empty?
- "1=0"
- else
- if block_given?
- statement_by_role.each do |role, statement|
- if s = yield(role, user)
- statement_by_role[role] = "(#{statement} AND (#{s}))"
- end
- end
- end
- "((#{base_statement}) AND (#{statement_by_role.values.join(' OR ')}))"
- end
- end
- end
-
- def principals
- @principals ||= Principal.active.joins(:members).where("#{Member.table_name}.project_id = ?", id).uniq
- end
-
- def users
- @users ||= User.active.joins(:members).where("#{Member.table_name}.project_id = ?", id).uniq
- end
-
- # Returns the Systemwide and project specific activities
- def activities(include_inactive=false)
- if include_inactive
- return all_activities
- else
- return active_activities
- end
- end
-
- # Will create a new Project specific Activity or update an existing one
- #
- # This will raise a ActiveRecord::Rollback if the TimeEntryActivity
- # does not successfully save.
- def update_or_create_time_entry_activity(id, activity_hash)
- if activity_hash.respond_to?(:has_key?) && activity_hash.has_key?('parent_id')
- self.create_time_entry_activity_if_needed(activity_hash)
- else
- activity = project.time_entry_activities.find_by_id(id.to_i)
- activity.update_attributes(activity_hash) if activity
- end
- end
-
- # Create a new TimeEntryActivity if it overrides a system TimeEntryActivity
- #
- # This will raise a ActiveRecord::Rollback if the TimeEntryActivity
- # does not successfully save.
- def create_time_entry_activity_if_needed(activity)
- if activity['parent_id']
-
- parent_activity = TimeEntryActivity.find(activity['parent_id'])
- activity['name'] = parent_activity.name
- activity['position'] = parent_activity.position
-
- if Enumeration.overridding_change?(activity, parent_activity)
- project_activity = self.time_entry_activities.create(activity)
-
- if project_activity.new_record?
- raise ActiveRecord::Rollback, "Overridding TimeEntryActivity was not successfully saved"
- else
- self.time_entries.update_all("activity_id = #{project_activity.id}", ["activity_id = ?", parent_activity.id])
- end
- end
- end
- end
-
- # Returns a :conditions SQL string that can be used to find the issues associated with this project.
- #
- # Examples:
- # project.project_condition(true) => "(projects.id = 1 OR (projects.lft > 1 AND projects.rgt < 10))"
- # project.project_condition(false) => "projects.id = 1"
- def project_condition(with_subprojects)
- cond = "#{Project.table_name}.id = #{id}"
- cond = "(#{cond} OR (#{Project.table_name}.lft > #{lft} AND #{Project.table_name}.rgt < #{rgt}))" if with_subprojects
- cond
- end
-
- def self.find(*args)
- if args.first && args.first.is_a?(String) && !args.first.match(/^\d*$/)
- project = find_by_identifier(*args)
- raise ActiveRecord::RecordNotFound, "Couldn't find Project with identifier=#{args.first}" if project.nil?
- project
- else
- super
- end
- end
-
- def self.find_by_param(*args)
- self.find(*args)
- end
-
- alias :base_reload :reload
- def reload(*args)
- @principals = nil
- @users = nil
- @shared_versions = nil
- @rolled_up_versions = nil
- @rolled_up_trackers = nil
- @all_issue_custom_fields = nil
- @all_time_entry_custom_fields = nil
- @to_param = nil
- @allowed_parents = nil
- @allowed_permissions = nil
- @actions_allowed = nil
- @start_date = nil
- @due_date = nil
- base_reload(*args)
- end
-
- def to_param
- # id is used for projects with a numeric identifier (compatibility)
- @to_param ||= (identifier.to_s =~ %r{^\d*$} ? id.to_s : identifier)
- end
-
- def active?
- self.status == STATUS_ACTIVE
- end
-
- def archived?
- self.status == STATUS_ARCHIVED
- end
-
- # Archives the project and its descendants
- def archive
- # Check that there is no issue of a non descendant project that is assigned
- # to one of the project or descendant versions
- v_ids = self_and_descendants.collect {|p| p.version_ids}.flatten
- if v_ids.any? &&
- Issue.
- includes(:project).
- where("#{Project.table_name}.lft < ? OR #{Project.table_name}.rgt > ?", lft, rgt).
- where("#{Issue.table_name}.fixed_version_id IN (?)", v_ids).
- exists?
- return false
- end
- Project.transaction do
- archive!
- end
- true
- end
-
- # Unarchives the project
- # All its ancestors must be active
- def unarchive
- return false if ancestors.detect {|a| !a.active?}
- update_attribute :status, STATUS_ACTIVE
- end
-
- def close
- self_and_descendants.status(STATUS_ACTIVE).update_all :status => STATUS_CLOSED
- end
-
- def reopen
- self_and_descendants.status(STATUS_CLOSED).update_all :status => STATUS_ACTIVE
- end
-
- # Returns an array of projects the project can be moved to
- # by the current user
- def allowed_parents
- return @allowed_parents if @allowed_parents
- @allowed_parents = Project.where(Project.allowed_to_condition(User.current, :add_subprojects)).all
- @allowed_parents = @allowed_parents - self_and_descendants
- if User.current.allowed_to?(:add_project, nil, :global => true) || (!new_record? && parent.nil?)
- @allowed_parents << nil
- end
- unless parent.nil? || @allowed_parents.empty? || @allowed_parents.include?(parent)
- @allowed_parents << parent
- end
- @allowed_parents
- end
-
- # Sets the parent of the project with authorization check
- def set_allowed_parent!(p)
- unless p.nil? || p.is_a?(Project)
- if p.to_s.blank?
- p = nil
- else
- p = Project.find_by_id(p)
- return false unless p
- end
- end
- if p.nil?
- if !new_record? && allowed_parents.empty?
- return false
- end
- elsif !allowed_parents.include?(p)
- return false
- end
- set_parent!(p)
- end
-
- # Sets the parent of the project
- # Argument can be either a Project, a String, a Fixnum or nil
- def set_parent!(p)
- unless p.nil? || p.is_a?(Project)
- if p.to_s.blank?
- p = nil
- else
- p = Project.find_by_id(p)
- return false unless p
- end
- end
- if p == parent && !p.nil?
- # Nothing to do
- true
- elsif p.nil? || (p.active? && move_possible?(p))
- set_or_update_position_under(p)
- Issue.update_versions_from_hierarchy_change(self)
- true
- else
- # Can not move to the given target
- false
- end
- end
-
- # Recalculates all lft and rgt values based on project names
- # Unlike Project.rebuild!, these values are recalculated even if the tree "looks" valid
- # Used in BuildProjectsTree migration
- def self.rebuild_tree!
- transaction do
- update_all "lft = NULL, rgt = NULL"
- rebuild!(false)
- end
- end
-
- # Returns an array of the trackers used by the project and its active sub projects
- def rolled_up_trackers
- @rolled_up_trackers ||=
- Tracker.
- joins(:projects).
- joins("JOIN #{EnabledModule.table_name} ON #{EnabledModule.table_name}.project_id = #{Project.table_name}.id AND #{EnabledModule.table_name}.name = 'issue_tracking'").
- select("DISTINCT #{Tracker.table_name}.*").
- where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> #{STATUS_ARCHIVED}", lft, rgt).
- sorted.
- all
- end
-
- # Closes open and locked project versions that are completed
- def close_completed_versions
- Version.transaction do
- versions.where(:status => %w(open locked)).all.each do |version|
- if version.completed?
- version.update_attribute(:status, 'closed')
- end
- end
- end
- end
-
- # Returns a scope of the Versions on subprojects
- def rolled_up_versions
- @rolled_up_versions ||=
- Version.
- includes(:project).
- where("#{Project.table_name}.lft >= ? AND #{Project.table_name}.rgt <= ? AND #{Project.table_name}.status <> ?", lft, rgt, STATUS_ARCHIVED)
- end
-
- # Returns a scope of the Versions used by the project
- def shared_versions
- if new_record?
- Version.
- includes(:project).
- where("#{Project.table_name}.status <> ? AND #{Version.table_name}.sharing = 'system'", STATUS_ARCHIVED)
- else
- @shared_versions ||= begin
- r = root? ? self : root
- Version.
- includes(:project).
- where("#{Project.table_name}.id = #{id}" +
- " OR (#{Project.table_name}.status <> #{Project::STATUS_ARCHIVED} AND (" +
- " #{Version.table_name}.sharing = 'system'" +
- " OR (#{Project.table_name}.lft >= #{r.lft} AND #{Project.table_name}.rgt <= #{r.rgt} AND #{Version.table_name}.sharing = 'tree')" +
- " OR (#{Project.table_name}.lft < #{lft} AND #{Project.table_name}.rgt > #{rgt} AND #{Version.table_name}.sharing IN ('hierarchy', 'descendants'))" +
- " OR (#{Project.table_name}.lft > #{lft} AND #{Project.table_name}.rgt < #{rgt} AND #{Version.table_name}.sharing = 'hierarchy')" +
- "))")
- end
- end
- end
-
- # Returns a hash of project users grouped by role
- def users_by_role
- members.includes(:user, :roles).all.inject({}) do |h, m|
- m.roles.each do |r|
- h[r] ||= []
- h[r] << m.user
- end
- h
- end
- end
-
- # Deletes all project's members
- def delete_all_members
- me, mr = Member.table_name, MemberRole.table_name
- connection.delete("DELETE FROM #{mr} WHERE #{mr}.member_id IN (SELECT #{me}.id FROM #{me} WHERE #{me}.project_id = #{id})")
- Member.delete_all(['project_id = ?', id])
- end
-
- # Users/groups issues can be assigned to
- def assignable_users
- assignable = Setting.issue_group_assignment? ? member_principals : members
- assignable.select {|m| m.roles.detect {|role| role.assignable?}}.collect {|m| m.principal}.sort
- end
-
- # Returns the mail adresses of users that should be always notified on project events
- def recipients
- notified_users.collect {|user| user.mail}
- end
-
- # Returns the users that should be notified on project events
- def notified_users
- # TODO: User part should be extracted to User#notify_about?
- members.select {|m| m.principal.present? && (m.mail_notification? || m.principal.mail_notification == 'all')}.collect {|m| m.principal}
- end
-
- # Returns a scope of all custom fields enabled for project issues
- # (explictly associated custom fields and custom fields enabled for all projects)
- def all_issue_custom_fields
- @all_issue_custom_fields ||= IssueCustomField.
- sorted.
- where("is_for_all = ? OR id IN (SELECT DISTINCT cfp.custom_field_id" +
- " FROM #{table_name_prefix}custom_fields_projects#{table_name_suffix} cfp" +
- " WHERE cfp.project_id = ?)", true, id)
- end
-
- # Returns an array of all custom fields enabled for project time entries
- # (explictly associated custom fields and custom fields enabled for all projects)
- def all_time_entry_custom_fields
- @all_time_entry_custom_fields ||= (TimeEntryCustomField.for_all + time_entry_custom_fields).uniq.sort
- end
-
- def project
- self
- end
-
- def <=>(project)
- name.downcase <=> project.name.downcase
- end
-
- def to_s
- name
- end
-
- # Returns a short description of the projects (first lines)
- def short_description(length = 255)
- description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
- end
-
- def css_classes
- s = 'project'
- s << ' root' if root?
- s << ' child' if child?
- s << (leaf? ? ' leaf' : ' parent')
- unless active?
- if archived?
- s << ' archived'
- else
- s << ' closed'
- end
- end
- s
- end
-
- # The earliest start date of a project, based on it's issues and versions
- def start_date
- @start_date ||= [
- issues.minimum('start_date'),
- shared_versions.minimum('effective_date'),
- Issue.fixed_version(shared_versions).minimum('start_date')
- ].compact.min
- end
-
- # The latest due date of an issue or version
- def due_date
- @due_date ||= [
- issues.maximum('due_date'),
- shared_versions.maximum('effective_date'),
- Issue.fixed_version(shared_versions).maximum('due_date')
- ].compact.max
- end
-
- def overdue?
- active? && !due_date.nil? && (due_date < Date.today)
- end
-
- # Returns the percent completed for this project, based on the
- # progress on it's versions.
- def completed_percent(options={:include_subprojects => false})
- if options.delete(:include_subprojects)
- total = self_and_descendants.collect(&:completed_percent).sum
-
- total / self_and_descendants.count
- else
- if versions.count > 0
- total = versions.collect(&:completed_percent).sum
-
- total / versions.count
- else
- 100
- end
- end
- end
-
- # Return true if this project allows to do the specified action.
- # action can be:
- # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
- # * a permission Symbol (eg. :edit_project)
- def allows_to?(action)
- if archived?
- # No action allowed on archived projects
- return false
- end
- unless active? || Redmine::AccessControl.read_action?(action)
- # No write action allowed on closed projects
- return false
- end
- # No action allowed on disabled modules
- if action.is_a? Hash
- allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
- else
- allowed_permissions.include? action
- end
- end
-
- def module_enabled?(module_name)
- module_name = module_name.to_s
- enabled_modules.detect {|m| m.name == module_name}
- end
-
- def enabled_module_names=(module_names)
- if module_names && module_names.is_a?(Array)
- module_names = module_names.collect(&:to_s).reject(&:blank?)
- self.enabled_modules = module_names.collect {|name| enabled_modules.detect {|mod| mod.name == name} || EnabledModule.new(:name => name)}
- else
- enabled_modules.clear
- end
- end
-
- # Returns an array of the enabled modules names
- def enabled_module_names
- enabled_modules.collect(&:name)
- end
-
- # Enable a specific module
- #
- # Examples:
- # project.enable_module!(:issue_tracking)
- # project.enable_module!("issue_tracking")
- def enable_module!(name)
- enabled_modules << EnabledModule.new(:name => name.to_s) unless module_enabled?(name)
- end
-
- # Disable a module if it exists
- #
- # Examples:
- # project.disable_module!(:issue_tracking)
- # project.disable_module!("issue_tracking")
- # project.disable_module!(project.enabled_modules.first)
- def disable_module!(target)
- target = enabled_modules.detect{|mod| target.to_s == mod.name} unless enabled_modules.include?(target)
- target.destroy unless target.blank?
- end
-
- safe_attributes 'name',
- 'description',
- 'homepage',
- 'is_public',
- 'identifier',
- 'custom_field_values',
- 'custom_fields',
- 'tracker_ids',
- 'issue_custom_field_ids'
-
- safe_attributes 'enabled_module_names',
- :if => lambda {|project, user| project.new_record? || user.allowed_to?(:select_project_modules, project) }
-
- safe_attributes 'inherit_members',
- :if => lambda {|project, user| project.parent.nil? || project.parent.visible?(user)}
-
- # Returns an array of projects that are in this project's hierarchy
- #
- # Example: parents, children, siblings
- def hierarchy
- parents = project.self_and_ancestors || []
- descendants = project.descendants || []
- project_hierarchy = parents | descendants # Set union
- end
-
- # Returns an auto-generated project identifier based on the last identifier used
- def self.next_identifier
- p = Project.order('id DESC').first
- p.nil? ? nil : p.identifier.to_s.succ
- end
-
- # Copies and saves the Project instance based on the +project+.
- # Duplicates the source project's:
- # * Wiki
- # * Versions
- # * Categories
- # * Issues
- # * Members
- # * Queries
- #
- # Accepts an +options+ argument to specify what to copy
- #
- # Examples:
- # project.copy(1) # => copies everything
- # project.copy(1, :only => 'members') # => copies members only
- # project.copy(1, :only => ['members', 'versions']) # => copies members and versions
- def copy(project, options={})
- project = project.is_a?(Project) ? project : Project.find(project)
-
- to_be_copied = %w(wiki versions issue_categories issues members queries boards)
- to_be_copied = to_be_copied & options[:only].to_a unless options[:only].nil?
-
- Project.transaction do
- if save
- reload
- to_be_copied.each do |name|
- send "copy_#{name}", project
- end
- Redmine::Hook.call_hook(:model_project_copy_before_save, :source_project => project, :destination_project => self)
- save
- end
- end
- end
-
- # Returns a new unsaved Project instance with attributes copied from +project+
- def self.copy_from(project)
- project = project.is_a?(Project) ? project : Project.find(project)
- # clear unique attributes
- attributes = project.attributes.dup.except('id', 'name', 'identifier', 'status', 'parent_id', 'lft', 'rgt')
- copy = Project.new(attributes)
- copy.enabled_modules = project.enabled_modules
- copy.trackers = project.trackers
- copy.custom_values = project.custom_values.collect {|v| v.clone}
- copy.issue_custom_fields = project.issue_custom_fields
- copy
- end
-
- # Yields the given block for each project with its level in the tree
- def self.project_tree(projects, &block)
- ancestors = []
- projects.sort_by(&:lft).each do |project|
- while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
- ancestors.pop
- end
- yield project, ancestors.size
- ancestors << project
- end
- end
-
- private
-
- def after_parent_changed(parent_was)
- remove_inherited_member_roles
- add_inherited_member_roles
- end
-
- def update_inherited_members
- if parent
- if inherit_members? && !inherit_members_was
- remove_inherited_member_roles
- add_inherited_member_roles
- elsif !inherit_members? && inherit_members_was
- remove_inherited_member_roles
- end
- end
- end
-
- def remove_inherited_member_roles
- member_roles = memberships.map(&:member_roles).flatten
- member_role_ids = member_roles.map(&:id)
- member_roles.each do |member_role|
- if member_role.inherited_from && !member_role_ids.include?(member_role.inherited_from)
- member_role.destroy
- end
- end
- end
-
- def add_inherited_member_roles
- if inherit_members? && parent
- parent.memberships.each do |parent_member|
- member = Member.find_or_new(self.id, parent_member.user_id)
- parent_member.member_roles.each do |parent_member_role|
- member.member_roles << MemberRole.new(:role => parent_member_role.role, :inherited_from => parent_member_role.id)
- end
- member.save!
- end
- end
- end
-
- # Copies wiki from +project+
- def copy_wiki(project)
- # Check that the source project has a wiki first
- unless project.wiki.nil?
- wiki = self.wiki || Wiki.new
- wiki.attributes = project.wiki.attributes.dup.except("id", "project_id")
- wiki_pages_map = {}
- project.wiki.pages.each do |page|
- # Skip pages without content
- next if page.content.nil?
- new_wiki_content = WikiContent.new(page.content.attributes.dup.except("id", "page_id", "updated_on"))
- new_wiki_page = WikiPage.new(page.attributes.dup.except("id", "wiki_id", "created_on", "parent_id"))
- new_wiki_page.content = new_wiki_content
- wiki.pages << new_wiki_page
- wiki_pages_map[page.id] = new_wiki_page
- end
-
- self.wiki = wiki
- wiki.save
- # Reproduce page hierarchy
- project.wiki.pages.each do |page|
- if page.parent_id && wiki_pages_map[page.id]
- wiki_pages_map[page.id].parent = wiki_pages_map[page.parent_id]
- wiki_pages_map[page.id].save
- end
- end
- end
- end
-
- # Copies versions from +project+
- def copy_versions(project)
- project.versions.each do |version|
- new_version = Version.new
- new_version.attributes = version.attributes.dup.except("id", "project_id", "created_on", "updated_on")
- self.versions << new_version
- end
- end
-
- # Copies issue categories from +project+
- def copy_issue_categories(project)
- project.issue_categories.each do |issue_category|
- new_issue_category = IssueCategory.new
- new_issue_category.attributes = issue_category.attributes.dup.except("id", "project_id")
- self.issue_categories << new_issue_category
- end
- end
-
- # Copies issues from +project+
- def copy_issues(project)
- # Stores the source issue id as a key and the copied issues as the
- # value. Used to map the two togeather for issue relations.
- issues_map = {}
-
- # Store status and reopen locked/closed versions
- version_statuses = versions.reject(&:open?).map {|version| [version, version.status]}
- version_statuses.each do |version, status|
- version.update_attribute :status, 'open'
- end
-
- # Get issues sorted by root_id, lft so that parent issues
- # get copied before their children
- project.issues.reorder('root_id, lft').all.each do |issue|
- new_issue = Issue.new
- new_issue.copy_from(issue, :subtasks => false, :link => false)
- new_issue.project = self
- # Changing project resets the custom field values
- # TODO: handle this in Issue#project=
- new_issue.custom_field_values = issue.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
- # Reassign fixed_versions by name, since names are unique per project
- if issue.fixed_version && issue.fixed_version.project == project
- new_issue.fixed_version = self.versions.detect {|v| v.name == issue.fixed_version.name}
- end
- # Reassign the category by name, since names are unique per project
- if issue.category
- new_issue.category = self.issue_categories.detect {|c| c.name == issue.category.name}
- end
- # Parent issue
- if issue.parent_id
- if copied_parent = issues_map[issue.parent_id]
- new_issue.parent_issue_id = copied_parent.id
- end
- end
-
- self.issues << new_issue
- if new_issue.new_record?
- logger.info "Project#copy_issues: issue ##{issue.id} could not be copied: #{new_issue.errors.full_messages}" if logger && logger.info
- else
- issues_map[issue.id] = new_issue unless new_issue.new_record?
- end
- end
-
- # Restore locked/closed version statuses
- version_statuses.each do |version, status|
- version.update_attribute :status, status
- end
-
- # Relations after in case issues related each other
- project.issues.each do |issue|
- new_issue = issues_map[issue.id]
- unless new_issue
- # Issue was not copied
- next
- end
-
- # Relations
- issue.relations_from.each do |source_relation|
- new_issue_relation = IssueRelation.new
- new_issue_relation.attributes = source_relation.attributes.dup.except("id", "issue_from_id", "issue_to_id")
- new_issue_relation.issue_to = issues_map[source_relation.issue_to_id]
- if new_issue_relation.issue_to.nil? && Setting.cross_project_issue_relations?
- new_issue_relation.issue_to = source_relation.issue_to
- end
- new_issue.relations_from << new_issue_relation
- end
-
- issue.relations_to.each do |source_relation|
- new_issue_relation = IssueRelation.new
- new_issue_relation.attributes = source_relation.attributes.dup.except("id", "issue_from_id", "issue_to_id")
- new_issue_relation.issue_from = issues_map[source_relation.issue_from_id]
- if new_issue_relation.issue_from.nil? && Setting.cross_project_issue_relations?
- new_issue_relation.issue_from = source_relation.issue_from
- end
- new_issue.relations_to << new_issue_relation
- end
- end
- end
-
- # Copies members from +project+
- def copy_members(project)
- # Copy users first, then groups to handle members with inherited and given roles
- members_to_copy = []
- members_to_copy += project.memberships.select {|m| m.principal.is_a?(User)}
- members_to_copy += project.memberships.select {|m| !m.principal.is_a?(User)}
-
- members_to_copy.each do |member|
- new_member = Member.new
- new_member.attributes = member.attributes.dup.except("id", "project_id", "created_on")
- # only copy non inherited roles
- # inherited roles will be added when copying the group membership
- role_ids = member.member_roles.reject(&:inherited?).collect(&:role_id)
- next if role_ids.empty?
- new_member.role_ids = role_ids
- new_member.project = self
- self.members << new_member
- end
- end
-
- # Copies queries from +project+
- def copy_queries(project)
- project.queries.each do |query|
- new_query = IssueQuery.new
- new_query.attributes = query.attributes.dup.except("id", "project_id", "sort_criteria")
- new_query.sort_criteria = query.sort_criteria if query.sort_criteria
- new_query.project = self
- new_query.user_id = query.user_id
- self.queries << new_query
- end
- end
-
- # Copies boards from +project+
- def copy_boards(project)
- project.boards.each do |board|
- new_board = Board.new
- new_board.attributes = board.attributes.dup.except("id", "project_id", "topics_count", "messages_count", "last_message_id")
- new_board.project = self
- self.boards << new_board
- end
- end
-
- def allowed_permissions
- @allowed_permissions ||= begin
- module_names = enabled_modules.loaded? ? enabled_modules.map(&:name) : enabled_modules.pluck(:name)
- Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name}
- end
- end
-
- def allowed_actions
- @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
- end
-
- # Returns all the active Systemwide and project specific activities
- def active_activities
- overridden_activity_ids = self.time_entry_activities.collect(&:parent_id)
-
- if overridden_activity_ids.empty?
- return TimeEntryActivity.shared.active
- else
- return system_activities_and_project_overrides
- end
- end
-
- # Returns all the Systemwide and project specific activities
- # (inactive and active)
- def all_activities
- overridden_activity_ids = self.time_entry_activities.collect(&:parent_id)
-
- if overridden_activity_ids.empty?
- return TimeEntryActivity.shared
- else
- return system_activities_and_project_overrides(true)
- end
- end
-
- # Returns the systemwide active activities merged with the project specific overrides
- def system_activities_and_project_overrides(include_inactive=false)
- if include_inactive
- return TimeEntryActivity.shared.
- where("id NOT IN (?)", self.time_entry_activities.collect(&:parent_id)).all +
- self.time_entry_activities
- else
- return TimeEntryActivity.shared.active.
- where("id NOT IN (?)", self.time_entry_activities.collect(&:parent_id)).all +
- self.time_entry_activities.active
- end
- end
-
- # Archives subprojects recursively
- def archive!
- children.each do |subproject|
- subproject.send :archive!
- end
- update_attribute :status, STATUS_ARCHIVED
- end
-
- def update_position_under_parent
- set_or_update_position_under(parent)
- end
-
- # Inserts/moves the project so that target's children or root projects stay alphabetically sorted
- def set_or_update_position_under(target_parent)
- parent_was = parent
- sibs = (target_parent.nil? ? self.class.roots : target_parent.children)
- to_be_inserted_before = sibs.sort_by {|c| c.name.to_s.downcase}.detect {|c| c.name.to_s.downcase > name.to_s.downcase }
-
- if to_be_inserted_before
- move_to_left_of(to_be_inserted_before)
- elsif target_parent.nil?
- if sibs.empty?
- # move_to_root adds the project in first (ie. left) position
- move_to_root
- else
- move_to_right_of(sibs.last) unless self == sibs.last
- end
- else
- # move_to_child_of adds the project in last (ie.right) position
- move_to_child_of(target_parent)
- end
- if parent_was != target_parent
- after_parent_changed(parent_was)
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/13/13f1c7e824023a07ff2178b5bb3f5f1ee4de792e.svn-base
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/13/13f1c7e824023a07ff2178b5bb3f5f1ee4de792e.svn-base Tue Sep 09 09:28:31 2014 +0100
@@ -0,0 +1,25 @@
+
+
+
Redmine 500 error
+
+
+
Internal error
+
An error occurred on the page you were trying to access.
+ If you continue to experience problems please contact your Redmine administrator for assistance.
+
If you are the Redmine administrator, check your log files for details about the error.
+
Back
+
+
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/13/13f3f51390f5b007f8a6b4667437b3436606259a.svn-base
--- a/.svn/pristine/13/13f3f51390f5b007f8a6b4667437b3436606259a.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module Redmine
- module Acts
- module ActivityProvider
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def acts_as_activity_provider(options = {})
- unless self.included_modules.include?(Redmine::Acts::ActivityProvider::InstanceMethods)
- cattr_accessor :activity_provider_options
- send :include, Redmine::Acts::ActivityProvider::InstanceMethods
- end
-
- options.assert_valid_keys(:type, :permission, :timestamp, :author_key, :find_options)
- self.activity_provider_options ||= {}
-
- # One model can provide different event types
- # We store these options in activity_provider_options hash
- event_type = options.delete(:type) || self.name.underscore.pluralize
-
- options[:timestamp] ||= "#{table_name}.created_on"
- options[:find_options] ||= {}
- options[:author_key] = "#{table_name}.#{options[:author_key]}" if options[:author_key].is_a?(Symbol)
- self.activity_provider_options[event_type] = options
- end
- end
-
- module InstanceMethods
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- # Returns events of type event_type visible by user that occured between from and to
- def find_events(event_type, user, from, to, options)
- provider_options = activity_provider_options[event_type]
- raise "#{self.name} can not provide #{event_type} events." if provider_options.nil?
-
- scope = self
-
- if from && to
- scope = scope.where("#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to)
- end
-
- if options[:author]
- return [] if provider_options[:author_key].nil?
- scope = scope.where("#{provider_options[:author_key]} = ?", options[:author].id)
- end
-
- if options[:limit]
- # id and creation time should be in same order in most cases
- scope = scope.reorder("#{table_name}.id DESC").limit(options[:limit])
- end
-
- if provider_options.has_key?(:permission)
- scope = scope.where(Project.allowed_to_condition(user, provider_options[:permission] || :view_project, options))
- elsif respond_to?(:visible)
- scope = scope.visible(user, options)
- else
- ActiveSupport::Deprecation.warn "acts_as_activity_provider with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
- scope = scope.where(Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym, options))
- end
-
- scope.all(provider_options[:find_options].dup)
- end
- end
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/15/1501976e33da8b363bb737aa1d51d7b528152400.svn-base
--- a/.svn/pristine/15/1501976e33da8b363bb737aa1d51d7b528152400.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../../test_helper', __FILE__)
-
-class Redmine::I18nTest < ActiveSupport::TestCase
- include Redmine::I18n
- include ActionView::Helpers::NumberHelper
-
- def setup
- User.current.language = nil
- end
-
- def teardown
- set_language_if_valid 'en'
- end
-
- def test_date_format_default
- set_language_if_valid 'en'
- today = Date.today
- Setting.date_format = ''
- assert_equal I18n.l(today), format_date(today)
- end
-
- def test_date_format
- set_language_if_valid 'en'
- today = Date.today
- Setting.date_format = '%d %m %Y'
- assert_equal today.strftime('%d %m %Y'), format_date(today)
- end
-
- def test_date_format_default_with_user_locale
- set_language_if_valid 'es'
- today = now = Time.parse('2011-02-20 14:00:00')
- Setting.date_format = '%d %B %Y'
- User.current.language = 'fr'
- s1 = "20 f\xc3\xa9vrier 2011"
- s1.force_encoding("UTF-8") if s1.respond_to?(:force_encoding)
- assert_equal s1, format_date(today)
- User.current.language = nil
- assert_equal '20 Febrero 2011', format_date(today)
- end
-
- def test_date_and_time_for_each_language
- Setting.date_format = ''
- valid_languages.each do |lang|
- set_language_if_valid lang
- assert_nothing_raised "#{lang} failure" do
- format_date(Date.today)
- format_time(Time.now)
- format_time(Time.now, false)
- assert_not_equal 'default', ::I18n.l(Date.today, :format => :default),
- "date.formats.default missing in #{lang}"
- assert_not_equal 'time', ::I18n.l(Time.now, :format => :time),
- "time.formats.time missing in #{lang}"
- end
- assert l('date.day_names').is_a?(Array)
- assert_equal 7, l('date.day_names').size
-
- assert l('date.month_names').is_a?(Array)
- assert_equal 13, l('date.month_names').size
- end
- end
-
- def test_time_for_each_zone
- ActiveSupport::TimeZone.all.each do |zone|
- User.current.stubs(:time_zone).returns(zone.name)
- assert_nothing_raised "#{zone} failure" do
- format_time(Time.now)
- end
- end
- end
-
- def test_time_format
- set_language_if_valid 'en'
- now = Time.parse('2011-02-20 15:45:22')
- with_settings :time_format => '%H:%M' do
- with_settings :date_format => '' do
- assert_equal '02/20/2011 15:45', format_time(now)
- assert_equal '15:45', format_time(now, false)
- end
- with_settings :date_format => '%Y-%m-%d' do
- assert_equal '2011-02-20 15:45', format_time(now)
- assert_equal '15:45', format_time(now, false)
- end
- end
- end
-
- def test_time_format_default
- set_language_if_valid 'en'
- now = Time.parse('2011-02-20 15:45:22')
- with_settings :time_format => '' do
- with_settings :date_format => '' do
- assert_equal '02/20/2011 03:45 PM', format_time(now)
- assert_equal '03:45 PM', format_time(now, false)
- end
- with_settings :date_format => '%Y-%m-%d' do
- assert_equal '2011-02-20 03:45 PM', format_time(now)
- assert_equal '03:45 PM', format_time(now, false)
- end
- end
- end
-
- def test_time_format_default_with_user_locale
- set_language_if_valid 'en'
- User.current.language = 'fr'
- now = Time.parse('2011-02-20 15:45:22')
- with_settings :time_format => '' do
- with_settings :date_format => '' do
- assert_equal '20/02/2011 15:45', format_time(now)
- assert_equal '15:45', format_time(now, false)
- end
- with_settings :date_format => '%Y-%m-%d' do
- assert_equal '2011-02-20 15:45', format_time(now)
- assert_equal '15:45', format_time(now, false)
- end
- end
- end
-
- def test_utc_time_format
- set_language_if_valid 'en'
- now = Time.now
- Setting.date_format = '%d %m %Y'
- Setting.time_format = '%H %M'
- assert_equal now.strftime('%d %m %Y %H %M'), format_time(now.utc)
- assert_equal now.strftime('%H %M'), format_time(now.utc, false)
- end
-
- def test_number_to_human_size_for_each_language
- valid_languages.each do |lang|
- set_language_if_valid lang
- assert_nothing_raised "#{lang} failure" do
- size = number_to_human_size(257024)
- assert_match /251/, size
- end
- end
- end
-
- def test_day_name
- set_language_if_valid 'fr'
- assert_equal 'dimanche', day_name(0)
- assert_equal 'jeudi', day_name(4)
- end
-
- def test_day_letter
- set_language_if_valid 'fr'
- assert_equal 'd', day_letter(0)
- assert_equal 'j', day_letter(4)
- end
-
- def test_number_to_currency_for_each_language
- valid_languages.each do |lang|
- set_language_if_valid lang
- assert_nothing_raised "#{lang} failure" do
- number_to_currency(-1000.2)
- end
- end
- end
-
- def test_number_to_currency_default
- set_language_if_valid 'bs'
- assert_equal "KM -1000,20", number_to_currency(-1000.2)
- set_language_if_valid 'de'
- euro_sign = "\xe2\x82\xac"
- euro_sign.force_encoding('UTF-8') if euro_sign.respond_to?(:force_encoding)
- assert_equal "-1000,20 #{euro_sign}", number_to_currency(-1000.2)
- end
-
- def test_valid_languages
- assert valid_languages.is_a?(Array)
- assert valid_languages.first.is_a?(Symbol)
- end
-
- def test_languages_options
- options = languages_options
- assert options.is_a?(Array)
- assert_equal valid_languages.size, options.size
- assert_nil options.detect {|option| !option.is_a?(Array)}
- assert_nil options.detect {|option| option.size != 2}
- assert_nil options.detect {|option| !option.first.is_a?(String) || !option.last.is_a?(String)}
- assert_include ["English", "en"], options
- ja = "Japanese (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)"
- ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
- assert_include [ja, "ja"], options
- end
-
- def test_locales_validness
- lang_files_count = Dir["#{Rails.root}/config/locales/*.yml"].size
- assert_equal lang_files_count, valid_languages.size
- valid_languages.each do |lang|
- assert set_language_if_valid(lang)
- end
- set_language_if_valid('en')
- end
-
- def test_valid_language
- to_test = {'fr' => :fr,
- 'Fr' => :fr,
- 'zh' => :zh,
- 'zh-tw' => :"zh-TW",
- 'zh-TW' => :"zh-TW",
- 'zh-ZZ' => nil }
- to_test.each {|lang, expected| assert_equal expected, find_language(lang)}
- end
-
- def test_fallback
- ::I18n.backend.store_translations(:en, {:untranslated => "Untranslated string"})
- ::I18n.locale = 'en'
- assert_equal "Untranslated string", l(:untranslated)
- ::I18n.locale = 'fr'
- assert_equal "Untranslated string", l(:untranslated)
-
- ::I18n.backend.store_translations(:fr, {:untranslated => "Pas de traduction"})
- ::I18n.locale = 'en'
- assert_equal "Untranslated string", l(:untranslated)
- ::I18n.locale = 'fr'
- assert_equal "Pas de traduction", l(:untranslated)
- end
-
- def test_utf8
- set_language_if_valid 'ja'
- str_ja_yes = "\xe3\x81\xaf\xe3\x81\x84"
- i18n_ja_yes = l(:general_text_Yes)
- if str_ja_yes.respond_to?(:force_encoding)
- str_ja_yes.force_encoding('UTF-8')
- assert_equal "UTF-8", i18n_ja_yes.encoding.to_s
- end
- assert_equal str_ja_yes, i18n_ja_yes
- end
-
- def test_traditional_chinese_locale
- set_language_if_valid 'zh-TW'
- str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
- if str_tw.respond_to?(:force_encoding)
- str_tw.force_encoding('UTF-8')
- end
- assert_equal str_tw, l(:general_lang_name)
- end
-
- def test_french_locale
- set_language_if_valid 'fr'
- str_fr = "Fran\xc3\xa7ais"
- if str_fr.respond_to?(:force_encoding)
- str_fr.force_encoding('UTF-8')
- end
- assert_equal str_fr, l(:general_lang_name)
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/15/15b7222cb6b5695205873370eda995f4170a4d8e.svn-base
--- a/.svn/pristine/15/15b7222cb6b5695205873370eda995f4170a4d8e.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class MemberTest < ActiveSupport::TestCase
- fixtures :projects, :trackers, :issue_statuses, :issues,
- :enumerations, :users, :issue_categories,
- :projects_trackers,
- :roles,
- :member_roles,
- :members,
- :enabled_modules,
- :groups_users,
- :watchers,
- :journals, :journal_details,
- :messages,
- :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
- :boards
-
- include Redmine::I18n
-
- def setup
- @jsmith = Member.find(1)
- end
-
- def test_create
- member = Member.new(:project_id => 1, :user_id => 4, :role_ids => [1, 2])
- assert member.save
- member.reload
-
- assert_equal 2, member.roles.size
- assert_equal Role.find(1), member.roles.sort.first
- end
-
- def test_update
- assert_equal "eCookbook", @jsmith.project.name
- assert_equal "Manager", @jsmith.roles.first.name
- assert_equal "jsmith", @jsmith.user.login
-
- @jsmith.mail_notification = !@jsmith.mail_notification
- assert @jsmith.save
- end
-
- def test_update_roles
- assert_equal 1, @jsmith.roles.size
- @jsmith.role_ids = [1, 2]
- assert @jsmith.save
- assert_equal 2, @jsmith.reload.roles.size
- end
-
- def test_validate
- member = Member.new(:project_id => 1, :user_id => 2, :role_ids => [2])
- # same use can't have more than one membership for a project
- assert !member.save
-
- # must have one role at least
- user = User.new(:firstname => "new1", :lastname => "user1", :mail => "test_validate@somenet.foo")
- user.login = "test_validate"
- user.password, user.password_confirmation = "password", "password"
- assert user.save
-
- set_language_if_valid 'fr'
- member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [])
- assert !member.save
- assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
- str = "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)"
- str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
- assert_equal str, [member.errors.full_messages].flatten.join
- end
-
- def test_validate_member_role
- user = User.new(:firstname => "new1", :lastname => "user1", :mail => "test_validate@somenet.foo")
- user.login = "test_validate_member_role"
- user.password, user.password_confirmation = "password", "password"
- assert user.save
- member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [5])
- assert !member.save
- end
-
- def test_destroy
- category1 = IssueCategory.find(1)
- assert_equal @jsmith.user.id, category1.assigned_to_id
- assert_difference 'Member.count', -1 do
- assert_difference 'MemberRole.count', -1 do
- @jsmith.destroy
- end
- end
- assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
- category1.reload
- assert_nil category1.assigned_to_id
- end
-
- def test_sort_without_roles
- a = Member.new(:roles => [Role.first])
- b = Member.new
-
- assert_equal -1, a <=> b
- assert_equal 1, b <=> a
- end
-
- def test_sort_without_principal
- role = Role.first
- a = Member.new(:roles => [role], :principal => User.first)
- b = Member.new(:roles => [role])
-
- assert_equal -1, a <=> b
- assert_equal 1, b <=> a
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/15/15c19f10a4e2450833d4d36fd99f66518ba44283.svn-base
--- a/.svn/pristine/15/15c19f10a4e2450833d4d36fd99f66518ba44283.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::CustomFieldsTest < Redmine::ApiTest::Base
- fixtures :users, :custom_fields
-
- def setup
- Setting.rest_api_enabled = '1'
- end
-
- test "GET /custom_fields.xml should return custom fields" do
- get '/custom_fields.xml', {}, credentials('admin')
- assert_response :success
- assert_equal 'application/xml', response.content_type
-
- assert_select 'custom_fields' do
- assert_select 'custom_field' do
- assert_select 'name', :text => 'Database'
- assert_select 'id', :text => '2'
- assert_select 'customized_type', :text => 'issue'
- assert_select 'possible_values[type=array]' do
- assert_select 'possible_value>value', :text => 'PostgreSQL'
- end
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/15/15d709b3f6a05dc0aade44cd45030b0d995c1fdc.svn-base
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/15/15d709b3f6a05dc0aade44cd45030b0d995c1fdc.svn-base Tue Sep 09 09:28:31 2014 +0100
@@ -0,0 +1,23 @@
+
+
+
Redmine 404 error
+
+
+
Page not found
+
The page you were trying to access doesn't exist or has been removed.
+
Back
+
+
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/16/1611dde1fb0ec5f844a52d9ac947a7c023328e24.svn-base
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.svn/pristine/16/1611dde1fb0ec5f844a52d9ac947a7c023328e24.svn-base Tue Sep 09 09:28:31 2014 +0100
@@ -0,0 +1,38 @@
+# Redmine runs tests on own continuous integration server.
+# http://www.redmine.org/projects/redmine/wiki/Continuous_integration
+# You can also run tests on your environment.
+language: ruby
+rvm:
+ - 1.8.7
+ - 1.9.2
+ - 1.9.3
+ - 2.0
+ - jruby
+matrix:
+ allow_failures:
+ # SCM tests fail randomly due to IO.popen().
+ # https://github.com/jruby/jruby/issues/779
+ - rvm: jruby
+env:
+ - "TEST_SUITE=units DATABASE_ADAPTER=postgresql"
+ - "TEST_SUITE=functionals DATABASE_ADAPTER=postgresql"
+ - "TEST_SUITE=integration DATABASE_ADAPTER=postgresql"
+ - "TEST_SUITE=units DATABASE_ADAPTER=mysql"
+ - "TEST_SUITE=functionals DATABASE_ADAPTER=mysql"
+ - "TEST_SUITE=integration DATABASE_ADAPTER=mysql"
+ - "TEST_SUITE=units DATABASE_ADAPTER=sqlite3"
+ - "TEST_SUITE=functionals DATABASE_ADAPTER=sqlite3"
+ - "TEST_SUITE=integration DATABASE_ADAPTER=sqlite3"
+before_install:
+ - "sudo apt-get update -qq"
+ - "sudo apt-get --no-install-recommends install bzr cvs git mercurial subversion"
+script:
+ - "SCMS=bazaar,cvs,subversion,git,mercurial,filesystem"
+ - "export SCMS"
+ - "git --version"
+ - "bundle install"
+ - "RUN_ON_NOT_OFFICIAL='' RUBY_VER=1.9 BRANCH=trunk bundle exec rake config/database.yml"
+ - "bundle install"
+ - "JRUBY_OPTS=-J-Xmx1024m bundle exec rake ci"
+notifications:
+ email: false
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/16/163200e35f1d8c0484dc12a3ebb2256afa7733a8.svn-base
--- a/.svn/pristine/16/163200e35f1d8c0484dc12a3ebb2256afa7733a8.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,437 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module Redmine
- module MenuManager
- class MenuError < StandardError #:nodoc:
- end
-
- module MenuController
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- @@menu_items = Hash.new {|hash, key| hash[key] = {:default => key, :actions => {}}}
- mattr_accessor :menu_items
-
- # Set the menu item name for a controller or specific actions
- # Examples:
- # * menu_item :tickets # => sets the menu name to :tickets for the whole controller
- # * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
- # * menu_item :tickets, :only => [:list, :show] # => sets the menu name to :tickets for 2 actions only
- #
- # The default menu item name for a controller is controller_name by default
- # Eg. the default menu item name for ProjectsController is :projects
- def menu_item(id, options = {})
- if actions = options[:only]
- actions = [] << actions unless actions.is_a?(Array)
- actions.each {|a| menu_items[controller_name.to_sym][:actions][a.to_sym] = id}
- else
- menu_items[controller_name.to_sym][:default] = id
- end
- end
- end
-
- def menu_items
- self.class.menu_items
- end
-
- # Returns the menu item name according to the current action
- def current_menu_item
- @current_menu_item ||= menu_items[controller_name.to_sym][:actions][action_name.to_sym] ||
- menu_items[controller_name.to_sym][:default]
- end
-
- # Redirects user to the menu item of the given project
- # Returns false if user is not authorized
- def redirect_to_project_menu_item(project, name)
- item = Redmine::MenuManager.items(:project_menu).detect {|i| i.name.to_s == name.to_s}
- if item && User.current.allowed_to?(item.url, project) && (item.condition.nil? || item.condition.call(project))
- redirect_to({item.param => project}.merge(item.url))
- return true
- end
- false
- end
- end
-
- module MenuHelper
- # Returns the current menu item name
- def current_menu_item
- controller.current_menu_item
- end
-
- # Renders the application main menu
- def render_main_menu(project)
- render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
- end
-
- def display_main_menu?(project)
- menu_name = project && !project.new_record? ? :project_menu : :application_menu
- Redmine::MenuManager.items(menu_name).children.present?
- end
-
- def render_menu(menu, project=nil)
- links = []
- menu_items_for(menu, project) do |node|
- links << render_menu_node(node, project)
- end
- links.empty? ? nil : content_tag('ul', links.join("\n").html_safe)
- end
-
- def render_menu_node(node, project=nil)
- if node.children.present? || !node.child_menus.nil?
- return render_menu_node_with_children(node, project)
- else
- caption, url, selected = extract_node_details(node, project)
- return content_tag('li',
- render_single_menu_node(node, caption, url, selected))
- end
- end
-
- def render_menu_node_with_children(node, project=nil)
- caption, url, selected = extract_node_details(node, project)
-
- html = [].tap do |html|
- html << '
'
- # Parent
- html << render_single_menu_node(node, caption, url, selected)
-
- # Standard children
- standard_children_list = "".html_safe.tap do |child_html|
- node.children.each do |child|
- child_html << render_menu_node(child, project)
- end
- end
-
- html << content_tag(:ul, standard_children_list, :class => 'menu-children') unless standard_children_list.empty?
-
- # Unattached children
- unattached_children_list = render_unattached_children_menu(node, project)
- html << content_tag(:ul, unattached_children_list, :class => 'menu-children unattached') unless unattached_children_list.blank?
-
- html << ''
- end
- return html.join("\n").html_safe
- end
-
- # Returns a list of unattached children menu items
- def render_unattached_children_menu(node, project)
- return nil unless node.child_menus
-
- "".html_safe.tap do |child_html|
- unattached_children = node.child_menus.call(project)
- # Tree nodes support #each so we need to do object detection
- if unattached_children.is_a? Array
- unattached_children.each do |child|
- child_html << content_tag(:li, render_unattached_menu_item(child, project))
- end
- else
- raise MenuError, ":child_menus must be an array of MenuItems"
- end
- end
- end
-
- def render_single_menu_node(item, caption, url, selected)
- link_to(h(caption), url, item.html_options(:selected => selected))
- end
-
- def render_unattached_menu_item(menu_item, project)
- raise MenuError, ":child_menus must be an array of MenuItems" unless menu_item.is_a? MenuItem
-
- if User.current.allowed_to?(menu_item.url, project)
- link_to(h(menu_item.caption),
- menu_item.url,
- menu_item.html_options)
- end
- end
-
- def menu_items_for(menu, project=nil)
- items = []
- Redmine::MenuManager.items(menu).root.children.each do |node|
- if allowed_node?(node, User.current, project)
- if block_given?
- yield node
- else
- items << node # TODO: not used?
- end
- end
- end
- return block_given? ? nil : items
- end
-
- def extract_node_details(node, project=nil)
- item = node
- url = case item.url
- when Hash
- project.nil? ? item.url : {item.param => project}.merge(item.url)
- when Symbol
- send(item.url)
- else
- item.url
- end
- caption = item.caption(project)
- return [caption, url, (current_menu_item == item.name)]
- end
-
- # Checks if a user is allowed to access the menu item by:
- #
- # * Checking the url target (project only)
- # * Checking the conditions of the item
- def allowed_node?(node, user, project)
- if project && user && !user.allowed_to?(node.url, project)
- return false
- end
- if node.condition && !node.condition.call(project)
- # Condition that doesn't pass
- return false
- end
- return true
- end
- end
-
- class << self
- def map(menu_name)
- @items ||= {}
- mapper = Mapper.new(menu_name.to_sym, @items)
- if block_given?
- yield mapper
- else
- mapper
- end
- end
-
- def items(menu_name)
- @items[menu_name.to_sym] || MenuNode.new(:root, {})
- end
- end
-
- class Mapper
- attr_reader :menu, :menu_items
-
- def initialize(menu, items)
- items[menu] ||= MenuNode.new(:root, {})
- @menu = menu
- @menu_items = items[menu]
- end
-
- # Adds an item at the end of the menu. Available options:
- # * param: the parameter name that is used for the project id (default is :id)
- # * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
- # * caption that can be:
- # * a localized string Symbol
- # * a String
- # * a Proc that can take the project as argument
- # * before, after: specify where the menu item should be inserted (eg. :after => :activity)
- # * parent: menu item will be added as a child of another named menu (eg. :parent => :issues)
- # * children: a Proc that is called before rendering the item. The Proc should return an array of MenuItems, which will be added as children to this item.
- # eg. :children => Proc.new {|project| [Redmine::MenuManager::MenuItem.new(...)] }
- # * last: menu item will stay at the end (eg. :last => true)
- # * html_options: a hash of html options that are passed to link_to
- def push(name, url, options={})
- options = options.dup
-
- if options[:parent]
- subtree = self.find(options[:parent])
- if subtree
- target_root = subtree
- else
- target_root = @menu_items.root
- end
-
- else
- target_root = @menu_items.root
- end
-
- # menu item position
- if first = options.delete(:first)
- target_root.prepend(MenuItem.new(name, url, options))
- elsif before = options.delete(:before)
-
- if exists?(before)
- target_root.add_at(MenuItem.new(name, url, options), position_of(before))
- else
- target_root.add(MenuItem.new(name, url, options))
- end
-
- elsif after = options.delete(:after)
-
- if exists?(after)
- target_root.add_at(MenuItem.new(name, url, options), position_of(after) + 1)
- else
- target_root.add(MenuItem.new(name, url, options))
- end
-
- elsif options[:last] # don't delete, needs to be stored
- target_root.add_last(MenuItem.new(name, url, options))
- else
- target_root.add(MenuItem.new(name, url, options))
- end
- end
-
- # Removes a menu item
- def delete(name)
- if found = self.find(name)
- @menu_items.remove!(found)
- end
- end
-
- # Checks if a menu item exists
- def exists?(name)
- @menu_items.any? {|node| node.name == name}
- end
-
- def find(name)
- @menu_items.find {|node| node.name == name}
- end
-
- def position_of(name)
- @menu_items.each do |node|
- if node.name == name
- return node.position
- end
- end
- end
- end
-
- class MenuNode
- include Enumerable
- attr_accessor :parent
- attr_reader :last_items_count, :name
-
- def initialize(name, content = nil)
- @name = name
- @children = []
- @last_items_count = 0
- end
-
- def children
- if block_given?
- @children.each {|child| yield child}
- else
- @children
- end
- end
-
- # Returns the number of descendants + 1
- def size
- @children.inject(1) {|sum, node| sum + node.size}
- end
-
- def each &block
- yield self
- children { |child| child.each(&block) }
- end
-
- # Adds a child at first position
- def prepend(child)
- add_at(child, 0)
- end
-
- # Adds a child at given position
- def add_at(child, position)
- raise "Child already added" if find {|node| node.name == child.name}
-
- @children = @children.insert(position, child)
- child.parent = self
- child
- end
-
- # Adds a child as last child
- def add_last(child)
- add_at(child, -1)
- @last_items_count += 1
- child
- end
-
- # Adds a child
- def add(child)
- position = @children.size - @last_items_count
- add_at(child, position)
- end
- alias :<< :add
-
- # Removes a child
- def remove!(child)
- @children.delete(child)
- @last_items_count -= +1 if child && child.last
- child.parent = nil
- child
- end
-
- # Returns the position for this node in it's parent
- def position
- self.parent.children.index(self)
- end
-
- # Returns the root for this node
- def root
- root = self
- root = root.parent while root.parent
- root
- end
- end
-
- class MenuItem < MenuNode
- include Redmine::I18n
- attr_reader :name, :url, :param, :condition, :parent, :child_menus, :last
-
- def initialize(name, url, options)
- raise ArgumentError, "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
- raise ArgumentError, "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
- raise ArgumentError, "Cannot set the :parent to be the same as this item" if options[:parent] == name.to_sym
- raise ArgumentError, "Invalid option :children for menu item '#{name}'" if options[:children] && !options[:children].respond_to?(:call)
- @name = name
- @url = url
- @condition = options[:if]
- @param = options[:param] || :id
- @caption = options[:caption]
- @html_options = options[:html] || {}
- # Adds a unique class to each menu item based on its name
- @html_options[:class] = [@html_options[:class], @name.to_s.dasherize].compact.join(' ')
- @parent = options[:parent]
- @child_menus = options[:children]
- @last = options[:last] || false
- super @name.to_sym
- end
-
- def caption(project=nil)
- if @caption.is_a?(Proc)
- c = @caption.call(project).to_s
- c = @name.to_s.humanize if c.blank?
- c
- else
- if @caption.nil?
- l_or_humanize(name, :prefix => 'label_')
- else
- @caption.is_a?(Symbol) ? l(@caption) : @caption
- end
- end
- end
-
- def html_options(options={})
- if options[:selected]
- o = @html_options.dup
- o[:class] += ' selected'
- o
- else
- @html_options
- end
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/17/17aa6f42b9915157fc191f136c4be06527af6f55.svn-base
--- a/.svn/pristine/17/17aa6f42b9915157fc191f136c4be06527af6f55.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class Redmine::ApiTest::TrackersTest < Redmine::ApiTest::Base
- fixtures :trackers
-
- def setup
- Setting.rest_api_enabled = '1'
- end
-
- test "GET /trackers.xml should return trackers" do
- get '/trackers.xml'
-
- assert_response :success
- assert_equal 'application/xml', @response.content_type
- assert_tag :tag => 'trackers',
- :attributes => {:type => 'array'},
- :child => {
- :tag => 'tracker',
- :child => {
- :tag => 'id',
- :content => '2',
- :sibling => {
- :tag => 'name',
- :content => 'Feature request'
- }
- }
- }
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/17/17eeb63ea895552f87458a07894df799f570d379.svn-base
--- a/.svn/pristine/17/17eeb63ea895552f87458a07894df799f570d379.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module RolesHelper
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/18/182957517dcdfdb9bed4a7cc03f63aeef4b1c15d.svn-base
--- a/.svn/pristine/18/182957517dcdfdb9bed4a7cc03f63aeef4b1c15d.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-class UserPreference < ActiveRecord::Base
- belongs_to :user
- serialize :others
-
- attr_protected :others, :user_id
-
- before_save :set_others_hash
-
- def initialize(attributes=nil, *args)
- super
- self.others ||= {}
- end
-
- def set_others_hash
- self.others ||= {}
- end
-
- def [](attr_name)
- if has_attribute? attr_name
- super
- else
- others ? others[attr_name] : nil
- end
- end
-
- def []=(attr_name, value)
- if has_attribute? attr_name
- super
- else
- h = (read_attribute(:others) || {}).dup
- h.update(attr_name => value)
- write_attribute(:others, h)
- value
- end
- end
-
- def comments_sorting; self[:comments_sorting] end
- def comments_sorting=(order); self[:comments_sorting]=order end
-
- def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
- def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
-
- def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
- def no_self_notified=(value); self[:no_self_notified]=value; end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/18/183dca49dc870131da0c794df1c3f5f569d0e6e5.svn-base
--- a/.svn/pristine/18/183dca49dc870131da0c794df1c3f5f569d0e6e5.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module IssueStatusesHelper
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/18/18aaa55b2d77150962ade434e4a8c39b73c97814.svn-base
--- a/.svn/pristine/18/18aaa55b2d77150962ade434e4a8c39b73c97814.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class RepositoriesFilesystemControllerTest < ActionController::TestCase
- tests RepositoriesController
-
- fixtures :projects, :users, :roles, :members, :member_roles,
- :repositories, :enabled_modules
-
- REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
- PRJ_ID = 3
-
- def setup
- @ruby19_non_utf8_pass =
- (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
- User.current = nil
- Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
- @project = Project.find(PRJ_ID)
- @repository = Repository::Filesystem.create(
- :project => @project,
- :url => REPOSITORY_PATH,
- :path_encoding => ''
- )
- assert @repository
- end
-
- if File.directory?(REPOSITORY_PATH)
- def test_get_new
- @request.session[:user_id] = 1
- @project.repository.destroy
- get :new, :project_id => 'subproject1', :repository_scm => 'Filesystem'
- assert_response :success
- assert_template 'new'
- assert_kind_of Repository::Filesystem, assigns(:repository)
- assert assigns(:repository).new_record?
- end
-
- def test_browse_root
- @repository.fetch_changesets
- @repository.reload
- get :show, :id => PRJ_ID
- assert_response :success
- assert_template 'show'
- assert_not_nil assigns(:entries)
- assert assigns(:entries).size > 0
- assert_not_nil assigns(:changesets)
- assert assigns(:changesets).size == 0
-
- assert_no_tag 'input', :attributes => {:name => 'rev'}
- assert_no_tag 'a', :content => 'Statistics'
- assert_no_tag 'a', :content => 'Atom'
- end
-
- def test_show_no_extension
- get :entry, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
- assert_response :success
- assert_template 'entry'
- assert_tag :tag => 'th',
- :content => '1',
- :attributes => { :class => 'line-num' },
- :sibling => { :tag => 'td', :content => /TEST CAT/ }
- end
-
- def test_entry_download_no_extension
- get :raw, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
- assert_response :success
- assert_equal 'application/octet-stream', @response.content_type
- end
-
- def test_show_non_ascii_contents
- with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
- get :entry, :id => PRJ_ID,
- :path => repository_path_hash(['japanese', 'euc-jp.txt'])[:param]
- assert_response :success
- assert_template 'entry'
- assert_tag :tag => 'th',
- :content => '2',
- :attributes => { :class => 'line-num' },
- :sibling => { :tag => 'td', :content => /japanese/ }
- if @ruby19_non_utf8_pass
- puts "TODO: show repository file contents test fails in Ruby 1.9 " +
- "and Encoding.default_external is not UTF-8. " +
- "Current value is '#{Encoding.default_external.to_s}'"
- else
- str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
- str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
- assert_tag :tag => 'th',
- :content => '3',
- :attributes => { :class => 'line-num' },
- :sibling => { :tag => 'td', :content => /#{str_japanese}/ }
- end
- end
- end
-
- def test_show_utf16
- enc = (RUBY_VERSION == "1.9.2" ? 'UTF-16LE' : 'UTF-16')
- with_settings :repositories_encodings => enc do
- get :entry, :id => PRJ_ID,
- :path => repository_path_hash(['japanese', 'utf-16.txt'])[:param]
- assert_response :success
- assert_tag :tag => 'th',
- :content => '2',
- :attributes => { :class => 'line-num' },
- :sibling => { :tag => 'td', :content => /japanese/ }
- end
- end
-
- def test_show_text_file_should_send_if_too_big
- with_settings :file_max_size_displayed => 1 do
- get :entry, :id => PRJ_ID,
- :path => repository_path_hash(['japanese', 'big-file.txt'])[:param]
- assert_response :success
- assert_equal 'text/plain', @response.content_type
- end
- end
-
- def test_destroy_valid_repository
- @request.session[:user_id] = 1 # admin
-
- assert_difference 'Repository.count', -1 do
- delete :destroy, :id => @repository.id
- end
- assert_response 302
- @project.reload
- assert_nil @project.repository
- end
-
- def test_destroy_invalid_repository
- @request.session[:user_id] = 1 # admin
- @project.repository.destroy
- @repository = Repository::Filesystem.create!(
- :project => @project,
- :url => "/invalid",
- :path_encoding => ''
- )
-
- assert_difference 'Repository.count', -1 do
- delete :destroy, :id => @repository.id
- end
- assert_response 302
- @project.reload
- assert_nil @project.repository
- end
- else
- puts "Filesystem test repository NOT FOUND. Skipping functional tests !!!"
- def test_fake; assert true end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/18/18af7ca4dac0c217561ab69b8406264b81adb03a.svn-base
--- a/.svn/pristine/18/18af7ca4dac0c217561ab69b8406264b81adb03a.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-class UserCustomField < CustomField
- def type_name
- :label_user_plural
- end
-end
-
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/19/190e5bea2d5dc9984a86fa22ae8cc4dd749898ab.svn-base
--- a/.svn/pristine/19/190e5bea2d5dc9984a86fa22ae8cc4dd749898ab.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module Redmine
- module Search
-
- mattr_accessor :available_search_types
-
- @@available_search_types = []
-
- class << self
- def map(&block)
- yield self
- end
-
- # Registers a search provider
- def register(search_type, options={})
- search_type = search_type.to_s
- @@available_search_types << search_type unless @@available_search_types.include?(search_type)
- end
- end
-
- module Controller
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- @@default_search_scopes = Hash.new {|hash, key| hash[key] = {:default => nil, :actions => {}}}
- mattr_accessor :default_search_scopes
-
- # Set the default search scope for a controller or specific actions
- # Examples:
- # * search_scope :issues # => sets the search scope to :issues for the whole controller
- # * search_scope :issues, :only => :index
- # * search_scope :issues, :only => [:index, :show]
- def default_search_scope(id, options = {})
- if actions = options[:only]
- actions = [] << actions unless actions.is_a?(Array)
- actions.each {|a| default_search_scopes[controller_name.to_sym][:actions][a.to_sym] = id.to_s}
- else
- default_search_scopes[controller_name.to_sym][:default] = id.to_s
- end
- end
- end
-
- def default_search_scopes
- self.class.default_search_scopes
- end
-
- # Returns the default search scope according to the current action
- def default_search_scope
- @default_search_scope ||= default_search_scopes[controller_name.to_sym][:actions][action_name.to_sym] ||
- default_search_scopes[controller_name.to_sym][:default]
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/19/191c54aa364bc303830fb03453b541edfd9e5945.svn-base
--- a/.svn/pristine/19/191c54aa364bc303830fb03453b541edfd9e5945.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-module Redmine
- module Configuration
-
- # Configuration default values
- @defaults = {
- 'email_delivery' => nil,
- 'max_concurrent_ajax_uploads' => 2
- }
-
- @config = nil
-
- class << self
- # Loads the Redmine configuration file
- # Valid options:
- # *
:file: the configuration file to load (default: config/configuration.yml)
- # *
:env: the environment to load the configuration for (default: Rails.env)
- def load(options={})
- filename = options[:file] || File.join(Rails.root, 'config', 'configuration.yml')
- env = options[:env] || Rails.env
-
- @config = @defaults.dup
-
- load_deprecated_email_configuration(env)
- if File.file?(filename)
- @config.merge!(load_from_yaml(filename, env))
- end
-
- # Compatibility mode for those who copy email.yml over configuration.yml
- %w(delivery_method smtp_settings sendmail_settings).each do |key|
- if value = @config.delete(key)
- @config['email_delivery'] ||= {}
- @config['email_delivery'][key] = value
- end
- end
-
- if @config['email_delivery']
- ActionMailer::Base.perform_deliveries = true
- @config['email_delivery'].each do |k, v|
- v.symbolize_keys! if v.respond_to?(:symbolize_keys!)
- ActionMailer::Base.send("#{k}=", v)
- end
- end
-
- @config
- end
-
- # Returns a configuration setting
- def [](name)
- load unless @config
- @config[name]
- end
-
- # Yields a block with the specified hash configuration settings
- def with(settings)
- settings.stringify_keys!
- load unless @config
- was = settings.keys.inject({}) {|h,v| h[v] = @config[v]; h}
- @config.merge! settings
- yield if block_given?
- @config.merge! was
- end
-
- private
-
- def load_from_yaml(filename, env)
- yaml = nil
- begin
- yaml = YAML::load_file(filename)
- rescue ArgumentError
- $stderr.puts "Your Redmine configuration file located at #{filename} is not a valid YAML file and could not be loaded."
- exit 1
- end
- conf = {}
- if yaml.is_a?(Hash)
- if yaml['default']
- conf.merge!(yaml['default'])
- end
- if yaml[env]
- conf.merge!(yaml[env])
- end
- else
- $stderr.puts "Your Redmine configuration file located at #{filename} is not a valid Redmine configuration file."
- exit 1
- end
- conf
- end
-
- def load_deprecated_email_configuration(env)
- deprecated_email_conf = File.join(Rails.root, 'config', 'email.yml')
- if File.file?(deprecated_email_conf)
- warn "Storing outgoing emails configuration in config/email.yml is deprecated. You should now store it in config/configuration.yml using the email_delivery setting."
- @config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)})
- end
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/1a/1a3135bf503a709c26b5156223514133ddf98de3.svn-base
--- a/.svn/pristine/1a/1a3135bf503a709c26b5156223514133ddf98de3.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'diff'
-
-module Redmine
- module Helpers
- class Diff
- include ERB::Util
- include ActionView::Helpers::TagHelper
- include ActionView::Helpers::TextHelper
- attr_reader :diff, :words
-
- def initialize(content_to, content_from)
- @words = content_to.to_s.split(/(\s+)/)
- @words = @words.select {|word| word != ' '}
- words_from = content_from.to_s.split(/(\s+)/)
- words_from = words_from.select {|word| word != ' '}
- @diff = words_from.diff @words
- end
-
- def to_html
- words = self.words.collect{|word| h(word)}
- words_add = 0
- words_del = 0
- dels = 0
- del_off = 0
- diff.diffs.each do |diff|
- add_at = nil
- add_to = nil
- del_at = nil
- deleted = ""
- diff.each do |change|
- pos = change[1]
- if change[0] == "+"
- add_at = pos + dels unless add_at
- add_to = pos + dels
- words_add += 1
- else
- del_at = pos unless del_at
- deleted << ' ' unless deleted.empty?
- deleted << h(change[2])
- words_del += 1
- end
- end
- if add_at
- words[add_at] = '
'.html_safe + words[add_at]
- words[add_to] = words[add_to] + ''.html_safe
- end
- if del_at
- words.insert del_at - del_off + dels + words_add, '
'.html_safe + deleted + ''.html_safe
- dels += 1
- del_off += words_del
- words_del = 0
- end
- end
- words.join(' ').html_safe
- end
- end
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/1a/1a57484f351c2899093aa4b926665fc8327667ab.svn-base
--- a/.svn/pristine/1a/1a57484f351c2899093aa4b926665fc8327667ab.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../test_helper', __FILE__)
-
-class LayoutTest < ActionController::IntegrationTest
- fixtures :projects, :trackers, :issue_statuses, :issues,
- :enumerations, :users, :issue_categories,
- :projects_trackers,
- :roles,
- :member_roles,
- :members,
- :enabled_modules
-
- test "browsing to a missing page should render the base layout" do
- get "/users/100000000"
-
- assert_response :not_found
-
- # UsersController uses the admin layout by default
- assert_select "#admin-menu", :count => 0
- end
-
- test "browsing to an unauthorized page should render the base layout" do
- change_user_password('miscuser9', 'test1234')
-
- log_user('miscuser9','test1234')
-
- get "/admin"
- assert_response :forbidden
- assert_select "#admin-menu", :count => 0
- end
-
- def test_top_menu_and_search_not_visible_when_login_required
- with_settings :login_required => '1' do
- get '/'
- assert_select "#top-menu > ul", 0
- assert_select "#quick-search", 0
- end
- end
-
- def test_top_menu_and_search_visible_when_login_not_required
- with_settings :login_required => '0' do
- get '/'
- assert_select "#top-menu > ul"
- assert_select "#quick-search"
- end
- end
-
- def test_wiki_formatter_header_tags
- Role.anonymous.add_permission! :add_issues
-
- get '/projects/ecookbook/issues/new'
- assert_tag :script,
- :attributes => {:src => %r{^/javascripts/jstoolbar/jstoolbar-textile.min.js}},
- :parent => {:tag => 'head'}
- end
-
- def test_calendar_header_tags
- with_settings :default_language => 'fr' do
- get '/issues'
- assert_include "/javascripts/i18n/jquery.ui.datepicker-fr.js", response.body
- end
-
- with_settings :default_language => 'en-GB' do
- get '/issues'
- assert_include "/javascripts/i18n/jquery.ui.datepicker-en-GB.js", response.body
- end
-
- with_settings :default_language => 'en' do
- get '/issues'
- assert_not_include "/javascripts/i18n/jquery.ui.datepicker", response.body
- end
-
- with_settings :default_language => 'zh' do
- get '/issues'
- assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-CN.js", response.body
- end
-
- with_settings :default_language => 'zh-TW' do
- get '/issues'
- assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-TW.js", response.body
- end
-
- with_settings :default_language => 'pt' do
- get '/issues'
- assert_include "/javascripts/i18n/jquery.ui.datepicker-pt.js", response.body
- end
-
- with_settings :default_language => 'pt-BR' do
- get '/issues'
- assert_include "/javascripts/i18n/jquery.ui.datepicker-pt-BR.js", response.body
- end
- end
-
- def test_search_field_outside_project_should_link_to_global_search
- get '/'
- assert_select 'div#quick-search form[action=/search]'
- end
-
- def test_search_field_inside_project_should_link_to_project_search
- get '/projects/ecookbook'
- assert_select 'div#quick-search form[action=/projects/ecookbook/search]'
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/1a/1a5ac9a1d7cbc1a58738649fabccca79dc7633e5.svn-base
--- a/.svn/pristine/1a/1a5ac9a1d7cbc1a58738649fabccca79dc7633e5.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class RoutingWikisTest < ActionController::IntegrationTest
- def test_wikis_plural_admin_setup
- ["get", "post"].each do |method|
- assert_routing(
- { :method => method, :path => "/projects/ladida/wiki/destroy" },
- { :controller => 'wikis', :action => 'destroy', :id => 'ladida' }
- )
- end
- assert_routing(
- { :method => 'post', :path => "/projects/ladida/wiki" },
- { :controller => 'wikis', :action => 'edit', :id => 'ladida' }
- )
- end
-end
diff -r e248c7af89ec -r b450a9d58aed .svn/pristine/1a/1a8020fad87f2bec2c86c62dc30a6bf033a7c796.svn-base
--- a/.svn/pristine/1a/1a8020fad87f2bec2c86c62dc30a6bf033a7c796.svn-base Mon Mar 17 08:54:02 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1268 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require File.expand_path('../../../test_helper', __FILE__)
-
-class ApplicationHelperTest < ActionView::TestCase
- include Redmine::I18n
- include ERB::Util
- include Rails.application.routes.url_helpers
-
- fixtures :projects, :roles, :enabled_modules, :users,
- :repositories, :changesets,
- :trackers, :issue_statuses, :issues, :versions, :documents,
- :wikis, :wiki_pages, :wiki_contents,
- :boards, :messages, :news,
- :attachments, :enumerations
-
- def setup
- super
- set_tmp_attachments_directory
- @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82"
- if @russian_test.respond_to?(:force_encoding)
- @russian_test.force_encoding('UTF-8')
- end
- end
-
- test "#link_to_if_authorized for authorized user should allow using the :controller and :action for the target link" do
- User.current = User.find_by_login('admin')
-
- @project = Issue.first.project # Used by helper
- response = link_to_if_authorized('By controller/actionr',
- {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
- assert_match /href/, response
- end
-
- test "#link_to_if_authorized for unauthorized user should display nothing if user isn't authorized" do
- User.current = User.find_by_login('dlopper')
- @project = Project.find('private-child')
- issue = @project.issues.first
- assert !issue.visible?
-
- response = link_to_if_authorized('Never displayed',
- {:controller => 'issues', :action => 'show', :id => issue})
- assert_nil response
- end
-
- def test_auto_links
- to_test = {
- 'http://foo.bar' => '
http://foo.bar',
- 'http://foo.bar/~user' => '
http://foo.bar/~user',
- 'http://foo.bar.' => '
http://foo.bar.',
- 'https://foo.bar.' => '
https://foo.bar.',
- 'This is a link: http://foo.bar.' => 'This is a link:
http://foo.bar.',
- 'A link (eg. http://foo.bar).' => 'A link (eg.
http://foo.bar).',
- 'http://foo.bar/foo.bar#foo.bar.' => '
http://foo.bar/foo.bar#foo.bar.',
- 'http://www.foo.bar/Test_(foobar)' => '
http://www.foo.bar/Test_(foobar)',
- '(see inline link : http://www.foo.bar/Test_(foobar))' => '(see inline link :
http://www.foo.bar/Test_(foobar))',
- '(see inline link : http://www.foo.bar/Test)' => '(see inline link :
http://www.foo.bar/Test)',
- '(see inline link : http://www.foo.bar/Test).' => '(see inline link :
http://www.foo.bar/Test).',
- '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see
inline link)',
- '(see "inline link":http://www.foo.bar/Test)' => '(see
inline link)',
- '(see "inline link":http://www.foo.bar/Test).' => '(see
inline link).',
- 'www.foo.bar' => '
www.foo.bar',
- 'http://foo.bar/page?p=1&t=z&s=' => '
http://foo.bar/page?p=1&t=z&s=',
- 'http://foo.bar/page#125' => '
http://foo.bar/page#125',
- 'http://foo@www.bar.com' => '
http://foo@www.bar.com',
- 'http://foo:bar@www.bar.com' => '
http://foo:bar@www.bar.com',
- 'ftp://foo.bar' => '
ftp://foo.bar',
- 'ftps://foo.bar' => '
ftps://foo.bar',
- 'sftp://foo.bar' => '
sftp://foo.bar',
- # two exclamation marks
- 'http://example.net/path!602815048C7B5C20!302.html' => '
http://example.net/path!602815048C7B5C20!302.html',
- # escaping
- 'http://foo"bar' => '
http://foo"bar',
- # wrap in angle brackets
- '
' => '<http://foo.bar>',
- # invalid urls
- 'http://' => 'http://',
- 'www.' => 'www.',
- 'test-www.bar.com' => 'test-www.bar.com',
- }
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
-
- if 'ruby'.respond_to?(:encoding)
- def test_auto_links_with_non_ascii_characters
- to_test = {
- "http://foo.bar/#{@russian_test}" =>
- %|http://foo.bar/#{@russian_test}|
- }
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
- else
- puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version'
- end
-
- def test_auto_mailto
- to_test = {
- 'test@foo.bar' => 'test@foo.bar',
- 'test@www.foo.bar' => 'test@www.foo.bar',
- }
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
-
- def test_inline_images
- to_test = {
- '!http://foo.bar/image.jpg!' => '
',
- 'floating !>http://foo.bar/image.jpg!' => 'floating ',
- 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class
',
- 'with style !{width:100px;height:100px}http://foo.bar/image.jpg!' => 'with style
',
- 'with title !http://foo.bar/image.jpg(This is a title)!' => 'with title
',
- 'with title !http://foo.bar/image.jpg(This is a double-quoted "title")!' => 'with title
',
- }
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
-
- def test_inline_images_inside_tags
- raw = <<-RAW
-h1. !foo.png! Heading
-
-Centered image:
-
-p=. !bar.gif!
-RAW
-
- assert textilizable(raw).include?('
')
- assert textilizable(raw).include?('
')
- end
-
- def test_attached_images
- to_test = {
- 'Inline image: !logo.gif!' => 'Inline image:
',
- 'Inline image: !logo.GIF!' => 'Inline image:
',
- 'No match: !ogo.gif!' => 'No match:
',
- 'No match: !ogo.GIF!' => 'No match:
',
- # link image
- '!logo.gif!:http://foo.bar/' => '
',
- }
- attachments = Attachment.all
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text, :attachments => attachments) }
- end
-
- def test_attached_images_filename_extension
- set_tmp_attachments_directory
- a1 = Attachment.new(
- :container => Issue.find(1),
- :file => mock_file_with_options({:original_filename => "testtest.JPG"}),
- :author => User.find(1))
- assert a1.save
- assert_equal "testtest.JPG", a1.filename
- assert_equal "image/jpeg", a1.content_type
- assert a1.image?
-
- a2 = Attachment.new(
- :container => Issue.find(1),
- :file => mock_file_with_options({:original_filename => "testtest.jpeg"}),
- :author => User.find(1))
- assert a2.save
- assert_equal "testtest.jpeg", a2.filename
- assert_equal "image/jpeg", a2.content_type
- assert a2.image?
-
- a3 = Attachment.new(
- :container => Issue.find(1),
- :file => mock_file_with_options({:original_filename => "testtest.JPE"}),
- :author => User.find(1))
- assert a3.save
- assert_equal "testtest.JPE", a3.filename
- assert_equal "image/jpeg", a3.content_type
- assert a3.image?
-
- a4 = Attachment.new(
- :container => Issue.find(1),
- :file => mock_file_with_options({:original_filename => "Testtest.BMP"}),
- :author => User.find(1))
- assert a4.save
- assert_equal "Testtest.BMP", a4.filename
- assert_equal "image/x-ms-bmp", a4.content_type
- assert a4.image?
-
- to_test = {
- 'Inline image: !testtest.jpg!' =>
- 'Inline image:
',
- 'Inline image: !testtest.jpeg!' =>
- 'Inline image:
',
- 'Inline image: !testtest.jpe!' =>
- 'Inline image:
',
- 'Inline image: !testtest.bmp!' =>
- 'Inline image:
',
- }
-
- attachments = [a1, a2, a3, a4]
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text, :attachments => attachments) }
- end
-
- def test_attached_images_should_read_later
- set_fixtures_attachments_directory
- a1 = Attachment.find(16)
- assert_equal "testfile.png", a1.filename
- assert a1.readable?
- assert (! a1.visible?(User.anonymous))
- assert a1.visible?(User.find(2))
- a2 = Attachment.find(17)
- assert_equal "testfile.PNG", a2.filename
- assert a2.readable?
- assert (! a2.visible?(User.anonymous))
- assert a2.visible?(User.find(2))
- assert a1.created_on < a2.created_on
-
- to_test = {
- 'Inline image: !testfile.png!' =>
- 'Inline image:
',
- 'Inline image: !Testfile.PNG!' =>
- 'Inline image:
',
- }
- attachments = [a1, a2]
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text, :attachments => attachments) }
- set_tmp_attachments_directory
- end
-
- def test_textile_external_links
- to_test = {
- 'This is a "link":http://foo.bar' => 'This is a link',
- 'This is an intern "link":/foo/bar' => 'This is an intern link',
- '"link (Link title)":http://foo.bar' => 'link',
- '"link (Link title with "double-quotes")":http://foo.bar' => 'link',
- "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":\n\n\n\tAnother paragraph",
- # no multiline link text
- "This is a double quote \"on the first line\nand another on a second line\":test" => "This is a double quote \"on the first line
and another on a second line\":test",
- # mailto link
- "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "system administrator",
- # two exclamation marks
- '"a link":http://example.net/path!602815048C7B5C20!302.html' => 'a link',
- # escaping
- '"test":http://foo"bar' => 'test',
- }
- to_test.each { |text, result| assert_equal "
#{result}
", textilizable(text) }
- end
-
- if 'ruby'.respond_to?(:encoding)
- def test_textile_external_links_with_non_ascii_characters
- to_test = {
- %|This is a "link":http://foo.bar/#{@russian_test}| =>
- %|This is a link|
- }
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
- else
- puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version'
- end
-
- def test_redmine_links
- issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
- :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
- note_link = link_to('#3-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
- :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
- note_link2 = link_to('#3#note-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
- :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
-
- revision_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
- :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
- revision_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
- :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
-
- changeset_link2 = link_to('691322a8eb01e11fd7',
- {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
- :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
-
- document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
- :class => 'document')
-
- version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
- :class => 'version')
-
- board_url = {:controller => 'boards', :action => 'show', :id => 2, :project_id => 'ecookbook'}
-
- message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
-
- news_url = {:controller => 'news', :action => 'show', :id => 1}
-
- project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
-
- source_url = '/projects/ecookbook/repository/entry/some/file'
- source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
- source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
- source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
- source_url_with_branch = '/projects/ecookbook/repository/revisions/branch/entry/some/file'
-
- export_url = '/projects/ecookbook/repository/raw/some/file'
- export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
- export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
- export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
- export_url_with_branch = '/projects/ecookbook/repository/revisions/branch/raw/some/file'
-
- to_test = {
- # tickets
- '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
- # ticket notes
- '#3-14' => note_link,
- '#3#note-14' => note_link2,
- # should not ignore leading zero
- '#03' => '#03',
- # changesets
- 'r1' => revision_link,
- 'r1.' => "#{revision_link}.",
- 'r1, r2' => "#{revision_link}, #{revision_link2}",
- 'r1,r2' => "#{revision_link},#{revision_link2}",
- 'commit:691322a8eb01e11fd7' => changeset_link2,
- # documents
- 'document#1' => document_link,
- 'document:"Test document"' => document_link,
- # versions
- 'version#2' => version_link,
- 'version:1.0' => version_link,
- 'version:"1.0"' => version_link,
- # source
- 'source:some/file' => link_to('source:some/file', source_url, :class => 'source'),
- 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
- 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
- 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
- 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
- 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
- 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
- 'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
- 'source:/some/file@branch' => link_to('source:/some/file@branch', source_url_with_branch, :class => 'source'),
- 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
- 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
- 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
- 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
- # export
- 'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'),
- 'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
- 'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
- 'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
- 'export:/some/file@branch' => link_to('export:/some/file@branch', export_url_with_branch, :class => 'source download'),
- # forum
- 'forum#2' => link_to('Discussion', board_url, :class => 'board'),
- 'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
- # message
- 'message#4' => link_to('Post 2', message_url, :class => 'message'),
- 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
- # news
- 'news#1' => link_to('eCookbook first release !', news_url, :class => 'news'),
- 'news:"eCookbook first release !"' => link_to('eCookbook first release !', news_url, :class => 'news'),
- # project
- 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
- 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
- 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
- # not found
- '#0123456789' => '#0123456789',
- # invalid expressions
- 'source:' => 'source:',
- # url hash
- "http://foo.bar/FAQ#3" => 'http://foo.bar/FAQ#3',
- }
- @project = Project.find(1)
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text), "#{text} failed" }
- end
-
- def test_redmine_links_with_a_different_project_before_current_project
- vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
- vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
-
- @project = Project.find(3)
- assert_equal %(1.4.4 1.4.4
),
- textilizable("ecookbook:version:1.4.4 version:1.4.4")
- end
-
- def test_escaped_redmine_links_should_not_be_parsed
- to_test = [
- '#3.',
- '#3-14.',
- '#3#-note14.',
- 'r1',
- 'document#1',
- 'document:"Test document"',
- 'version#2',
- 'version:1.0',
- 'version:"1.0"',
- 'source:/some/file'
- ]
- @project = Project.find(1)
- to_test.each { |text| assert_equal "#{text}
", textilizable("!" + text), "#{text} failed" }
- end
-
- def test_cross_project_redmine_links
- source_link = link_to('ecookbook:source:/some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']},
- :class => 'source')
-
- changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
- :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
-
- to_test = {
- # documents
- 'document:"Test document"' => 'document:"Test document"',
- 'ecookbook:document:"Test document"' => 'Test document',
- 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
- # versions
- 'version:"1.0"' => 'version:"1.0"',
- 'ecookbook:version:"1.0"' => '1.0',
- 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
- # changeset
- 'r2' => 'r2',
- 'ecookbook:r2' => changeset_link,
- 'invalid:r2' => 'invalid:r2',
- # source
- 'source:/some/file' => 'source:/some/file',
- 'ecookbook:source:/some/file' => source_link,
- 'invalid:source:/some/file' => 'invalid:source:/some/file',
- }
- @project = Project.find(3)
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text), "#{text} failed" }
- end
-
- def test_multiple_repositories_redmine_links
- svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
- Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
- hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
- Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
-
- changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
- :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
- svn_changeset_link = link_to('svn_repo-1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn_repo-1', :rev => 123},
- :class => 'changeset', :title => '')
- hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
- :class => 'changeset', :title => '')
-
- source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
- hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
-
- to_test = {
- 'r2' => changeset_link,
- 'svn_repo-1|r123' => svn_changeset_link,
- 'invalid|r123' => 'invalid|r123',
- 'commit:hg1|abcd' => hg_changeset_link,
- 'commit:invalid|abcd' => 'commit:invalid|abcd',
- # source
- 'source:some/file' => source_link,
- 'source:hg1|some/file' => hg_source_link,
- 'source:invalid|some/file' => 'source:invalid|some/file',
- }
-
- @project = Project.find(1)
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text), "#{text} failed" }
- end
-
- def test_cross_project_multiple_repositories_redmine_links
- svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
- Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
- hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
- Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
-
- changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
- :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
- svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
- :class => 'changeset', :title => '')
- hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
- :class => 'changeset', :title => '')
-
- source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
- hg_source_link = link_to('ecookbook:source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
-
- to_test = {
- 'ecookbook:r2' => changeset_link,
- 'ecookbook:svn1|r123' => svn_changeset_link,
- 'ecookbook:invalid|r123' => 'ecookbook:invalid|r123',
- 'ecookbook:commit:hg1|abcd' => hg_changeset_link,
- 'ecookbook:commit:invalid|abcd' => 'ecookbook:commit:invalid|abcd',
- 'invalid:commit:invalid|abcd' => 'invalid:commit:invalid|abcd',
- # source
- 'ecookbook:source:some/file' => source_link,
- 'ecookbook:source:hg1|some/file' => hg_source_link,
- 'ecookbook:source:invalid|some/file' => 'ecookbook:source:invalid|some/file',
- 'invalid:source:invalid|some/file' => 'invalid:source:invalid|some/file',
- }
-
- @project = Project.find(3)
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text), "#{text} failed" }
- end
-
- def test_redmine_links_git_commit
- changeset_link = link_to('abcd',
- {
- :controller => 'repositories',
- :action => 'revision',
- :id => 'subproject1',
- :rev => 'abcd',
- },
- :class => 'changeset', :title => 'test commit')
- to_test = {
- 'commit:abcd' => changeset_link,
- }
- @project = Project.find(3)
- r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
- assert r
- c = Changeset.new(:repository => r,
- :committed_on => Time.now,
- :revision => 'abcd',
- :scmid => 'abcd',
- :comments => 'test commit')
- assert( c.save )
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
-
- # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
- def test_redmine_links_darcs_commit
- changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
- {
- :controller => 'repositories',
- :action => 'revision',
- :id => 'subproject1',
- :rev => '123',
- },
- :class => 'changeset', :title => 'test commit')
- to_test = {
- 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
- }
- @project = Project.find(3)
- r = Repository::Darcs.create!(
- :project => @project, :url => '/tmp/test/darcs',
- :log_encoding => 'UTF-8')
- assert r
- c = Changeset.new(:repository => r,
- :committed_on => Time.now,
- :revision => '123',
- :scmid => '20080308225258-98289-abcd456efg.gz',
- :comments => 'test commit')
- assert( c.save )
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
-
- def test_redmine_links_mercurial_commit
- changeset_link_rev = link_to('r123',
- {
- :controller => 'repositories',
- :action => 'revision',
- :id => 'subproject1',
- :rev => '123' ,
- },
- :class => 'changeset', :title => 'test commit')
- changeset_link_commit = link_to('abcd',
- {
- :controller => 'repositories',
- :action => 'revision',
- :id => 'subproject1',
- :rev => 'abcd' ,
- },
- :class => 'changeset', :title => 'test commit')
- to_test = {
- 'r123' => changeset_link_rev,
- 'commit:abcd' => changeset_link_commit,
- }
- @project = Project.find(3)
- r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
- assert r
- c = Changeset.new(:repository => r,
- :committed_on => Time.now,
- :revision => '123',
- :scmid => 'abcd',
- :comments => 'test commit')
- assert( c.save )
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
-
- def test_attachment_links
- to_test = {
- 'attachment:error281.txt' => 'error281.txt'
- }
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
- end
-
- def test_attachment_link_should_link_to_latest_attachment
- set_tmp_attachments_directory
- a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
- a2 = Attachment.generate!(:filename => "test.txt")
-
- assert_equal %(test.txt
),
- textilizable('attachment:test.txt', :attachments => [a1, a2])
- end
-
- def test_wiki_links
- russian_eacape = CGI.escape(@russian_test)
- to_test = {
- '[[CookBook documentation]]' => 'CookBook documentation',
- '[[Another page|Page]]' => 'Page',
- # title content should be formatted
- '[[Another page|With _styled_ *title*]]' => 'With styled title',
- '[[Another page|With title containing HTML entities & markups]]' => 'With title containing <strong>HTML entities & markups</strong>',
- # link with anchor
- '[[CookBook documentation#One-section]]' => 'CookBook documentation',
- '[[Another page#anchor|Page]]' => 'Page',
- # UTF8 anchor
- "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
- %|#{@russian_test}|,
- # page that doesn't exist
- '[[Unknown page]]' => 'Unknown page',
- '[[Unknown page|404]]' => '404',
- # link to another project wiki
- '[[onlinestore:]]' => 'onlinestore',
- '[[onlinestore:|Wiki]]' => 'Wiki',
- '[[onlinestore:Start page]]' => 'Start page',
- '[[onlinestore:Start page|Text]]' => 'Text',
- '[[onlinestore:Unknown page]]' => 'Unknown page',
- # striked through link
- '-[[Another page|Page]]-' => 'Page',
- '-[[Another page|Page]] link-' => 'Page link',
- # escaping
- '![[Another page|Page]]' => '[[Another page|Page]]',
- # project does not exist
- '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
- '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
- }
-
- @project = Project.find(1)
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text) }
- end
-
- def test_wiki_links_within_local_file_generation_context
-
- to_test = {
- # link to a page
- '[[CookBook documentation]]' => 'CookBook documentation',
- '[[CookBook documentation|documentation]]' => 'documentation',
- '[[CookBook documentation#One-section]]' => 'CookBook documentation',
- '[[CookBook documentation#One-section|documentation]]' => 'documentation',
- # page that doesn't exist
- '[[Unknown page]]' => 'Unknown page',
- '[[Unknown page|404]]' => '404',
- '[[Unknown page#anchor]]' => 'Unknown page',
- '[[Unknown page#anchor|404]]' => '404',
- }
-
- @project = Project.find(1)
-
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text, :wiki_links => :local) }
- end
-
- def test_wiki_links_within_wiki_page_context
-
- page = WikiPage.find_by_title('Another_page' )
-
- to_test = {
- # link to another page
- '[[CookBook documentation]]' => 'CookBook documentation',
- '[[CookBook documentation|documentation]]' => 'documentation',
- '[[CookBook documentation#One-section]]' => 'CookBook documentation',
- '[[CookBook documentation#One-section|documentation]]' => 'documentation',
- # link to the current page
- '[[Another page]]' => 'Another page',
- '[[Another page|Page]]' => 'Page',
- '[[Another page#anchor]]' => 'Another page',
- '[[Another page#anchor|Page]]' => 'Page',
- # page that doesn't exist
- '[[Unknown page]]' => 'Unknown page',
- '[[Unknown page|404]]' => '404',
- '[[Unknown page#anchor]]' => 'Unknown page',
- '[[Unknown page#anchor|404]]' => '404',
- }
-
- @project = Project.find(1)
-
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(WikiContent.new( :text => text, :page => page ), :text) }
- end
-
- def test_wiki_links_anchor_option_should_prepend_page_title_to_href
-
- to_test = {
- # link to a page
- '[[CookBook documentation]]' => 'CookBook documentation',
- '[[CookBook documentation|documentation]]' => 'documentation',
- '[[CookBook documentation#One-section]]' => 'CookBook documentation',
- '[[CookBook documentation#One-section|documentation]]' => 'documentation',
- # page that doesn't exist
- '[[Unknown page]]' => 'Unknown page',
- '[[Unknown page|404]]' => '404',
- '[[Unknown page#anchor]]' => 'Unknown page',
- '[[Unknown page#anchor|404]]' => '404',
- }
-
- @project = Project.find(1)
-
- to_test.each { |text, result| assert_equal "#{result}
", textilizable(text, :wiki_links => :anchor) }
- end
-
- def test_html_tags
- to_test = {
- "content
" => "<div>content</div>
",
- "content
" => "<div class=\"bold\">content</div>
",
- "" => "<script>some script;</script>
",
- # do not escape pre/code tags
- "\nline 1\nline2
" => "\nline 1\nline2
",
- "\nline 1\nline2
" => "\nline 1\nline2
",
- "content
" => "<div>content</div>
",
- "HTML comment: " => "HTML comment: <!-- no comments -->
",
- "
-<%= yield :header_tags -%>
-
-
-
-
-
-
-
-
-
-
-
-
-
- <%= render_flash_messages %>
- <%= yield %>
- <%= call_hook :view_layouts_base_content %>
-
-
-
-
-
-
<%= l(:label_loading) %>
-
-
-
-
-
-<%= call_hook :view_layouts_base_body_bottom %>
-
-