Mercurial > hg > soundsoftware-site
changeset 118:b859cc0c4fa1 cannam
Merge from branch "redmine-1.1"
author | Chris Cannam |
---|---|
date | Thu, 13 Jan 2011 13:21:03 +0000 |
parents | 8a205cc048de (diff) af80e5618e9b (current diff) |
children | cd2282d2aa55 |
files | app/controllers/application_controller.rb app/controllers/issues_controller.rb app/controllers/users_controller.rb app/helpers/application_helper.rb app/helpers/repositories_helper.rb app/models/changeset.rb app/models/issue.rb app/models/repository.rb app/models/repository/git.rb app/models/repository/mercurial.rb app/models/user.rb app/sweepers/.svn/all-wcprops app/views/account/.svn/all-wcprops app/views/activities/.svn/all-wcprops app/views/admin/.svn/all-wcprops app/views/attachments/.svn/all-wcprops app/views/auth_sources/.svn/all-wcprops app/views/auto_completes/.svn/all-wcprops app/views/boards/.svn/all-wcprops app/views/calendars/.svn/all-wcprops app/views/common/.svn/all-wcprops app/views/context_menus/.svn/all-wcprops app/views/custom_fields/.svn/all-wcprops app/views/documents/.svn/all-wcprops app/views/enumerations/.svn/all-wcprops app/views/files/.svn/all-wcprops app/views/groups/.svn/all-wcprops app/views/issue_categories/.svn/all-wcprops app/views/issue_statuses/.svn/all-wcprops app/views/issues/.svn/prop-base/index.xml.builder.svn-base app/views/issues/.svn/prop-base/show.xml.builder.svn-base app/views/issues/.svn/text-base/index.xml.builder.svn-base app/views/issues/.svn/text-base/show.xml.builder.svn-base app/views/issues/index.xml.builder app/views/issues/show.xml.builder app/views/journals/.svn/all-wcprops app/views/layouts/base.rhtml app/views/ldap_auth_sources/.svn/all-wcprops app/views/mailer/.svn/all-wcprops app/views/members/.svn/all-wcprops app/views/messages/.svn/all-wcprops app/views/my/.svn/all-wcprops app/views/my/blocks/.svn/all-wcprops app/views/previews/.svn/all-wcprops app/views/projects/.svn/prop-base/index.xml.builder.svn-base app/views/projects/.svn/prop-base/show.xml.builder.svn-base app/views/projects/.svn/text-base/index.xml.builder.svn-base app/views/projects/.svn/text-base/show.xml.builder.svn-base app/views/projects/_form.rhtml app/views/projects/index.xml.builder app/views/projects/show.xml.builder app/views/queries/.svn/all-wcprops app/views/reports/.svn/all-wcprops app/views/repositories/revision.rhtml app/views/roles/.svn/all-wcprops app/views/search/.svn/all-wcprops app/views/settings/_general.rhtml app/views/time_entry_reports/.svn/all-wcprops app/views/trackers/.svn/all-wcprops app/views/users/_form.rhtml app/views/versions/.svn/all-wcprops app/views/watchers/.svn/all-wcprops app/views/welcome/.svn/all-wcprops app/views/wikis/.svn/all-wcprops config/environments/.svn/all-wcprops config/locales/bg.yml config/locales/bs.yml config/locales/ca.yml config/locales/cs.yml config/locales/da.yml config/locales/de.yml config/locales/el.yml config/locales/en-GB.yml config/locales/en.yml config/locales/es.yml config/locales/eu.yml config/locales/fi.yml config/locales/fr.yml config/locales/gl.yml config/locales/he.yml config/locales/hr.yml config/locales/hu.yml config/locales/id.yml config/locales/it.yml config/locales/ja.yml config/locales/ko.yml config/locales/lt.yml config/locales/lv.yml config/locales/mk.yml config/locales/mn.yml config/locales/nl.yml config/locales/no.yml config/locales/pl.yml config/locales/pt-BR.yml config/locales/pt.yml config/locales/ro.yml config/locales/ru.yml config/locales/sk.yml config/locales/sl.yml config/locales/sr-YU.yml config/locales/sr.yml config/locales/sv.yml config/locales/th.yml config/locales/tr.yml config/locales/uk.yml config/locales/vi.yml config/locales/zh-TW.yml config/locales/zh.yml config/settings.yml extra/.svn/all-wcprops extra/mail_handler/.svn/all-wcprops extra/sample_plugin/.svn/all-wcprops extra/sample_plugin/app/.svn/all-wcprops extra/sample_plugin/app/controllers/.svn/all-wcprops extra/sample_plugin/app/models/.svn/all-wcprops extra/sample_plugin/app/views/.svn/all-wcprops extra/sample_plugin/app/views/example/.svn/all-wcprops extra/sample_plugin/app/views/my/.svn/all-wcprops extra/sample_plugin/app/views/my/blocks/.svn/all-wcprops extra/sample_plugin/app/views/settings/.svn/all-wcprops extra/sample_plugin/assets/.svn/all-wcprops extra/sample_plugin/assets/images/.svn/all-wcprops extra/sample_plugin/assets/stylesheets/.svn/all-wcprops extra/sample_plugin/config/.svn/all-wcprops extra/sample_plugin/config/locales/.svn/all-wcprops extra/sample_plugin/db/.svn/all-wcprops extra/sample_plugin/db/migrate/.svn/all-wcprops extra/svn/.svn/all-wcprops files/.svn/all-wcprops lib/SVG/.svn/all-wcprops lib/SVG/Graph/.svn/all-wcprops lib/generators/.svn/all-wcprops lib/generators/redmine_plugin/.svn/all-wcprops lib/generators/redmine_plugin/templates/.svn/all-wcprops lib/generators/redmine_plugin_controller/.svn/all-wcprops lib/generators/redmine_plugin_controller/templates/.svn/all-wcprops lib/generators/redmine_plugin_model/.svn/all-wcprops lib/generators/redmine_plugin_model/templates/.svn/all-wcprops lib/plugins/.svn/all-wcprops lib/redmine/activity/.svn/all-wcprops lib/redmine/core_ext/.svn/all-wcprops lib/redmine/core_ext/string/.svn/all-wcprops lib/redmine/default_data/.svn/all-wcprops lib/redmine/export/.svn/all-wcprops lib/redmine/scm/adapters/abstract_adapter.rb lib/redmine/scm/adapters/mercurial/hg-template-0.9.5.tmpl lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl lib/redmine/scm/adapters/mercurial_adapter.rb lib/redmine/views/my_page/.svn/all-wcprops lib/redmine/wiki_formatting/.svn/all-wcprops lib/redmine/wiki_formatting/textile/.svn/all-wcprops log/.svn/all-wcprops public/help/.svn/all-wcprops public/images/files/.svn/all-wcprops public/images/jstoolbar/.svn/all-wcprops public/javascripts/calendar/.svn/all-wcprops public/javascripts/calendar/lang/.svn/all-wcprops public/javascripts/jstoolbar/.svn/all-wcprops public/javascripts/jstoolbar/lang/.svn/all-wcprops public/stylesheets/application.css public/themes/.svn/all-wcprops public/themes/alternate/.svn/all-wcprops public/themes/alternate/stylesheets/.svn/all-wcprops public/themes/classic/.svn/all-wcprops public/themes/classic/images/.svn/all-wcprops public/themes/classic/stylesheets/.svn/all-wcprops script/.svn/all-wcprops script/performance/.svn/all-wcprops script/process/.svn/all-wcprops test/exemplars/.svn/all-wcprops test/fixtures/diffs/.svn/all-wcprops test/fixtures/encoding/.svn/all-wcprops test/fixtures/files/.svn/all-wcprops test/fixtures/ldap/.svn/all-wcprops test/fixtures/mailer/.svn/all-wcprops test/fixtures/repositories/.svn/prop-base/mercurial_repository.tar.gz.svn-base test/fixtures/repositories/.svn/text-base/mercurial_repository.tar.gz.svn-base test/fixtures/repositories/mercurial_repository.tar.gz test/mocks/.svn/all-wcprops test/mocks/development/.svn/all-wcprops test/mocks/test/.svn/all-wcprops tmp/.svn/all-wcprops tmp/cache/.svn/all-wcprops tmp/sessions/.svn/all-wcprops tmp/sockets/.svn/all-wcprops tmp/test/.svn/all-wcprops vendor/gems/.svn/all-wcprops vendor/gems/rubytree-0.5.2/.svn/all-wcprops vendor/gems/rubytree-0.5.2/lib/.svn/all-wcprops vendor/gems/rubytree-0.5.2/lib/tree/.svn/all-wcprops vendor/gems/rubytree-0.5.2/test/.svn/all-wcprops vendor/plugins/acts_as_activity_provider/.svn/all-wcprops vendor/plugins/acts_as_activity_provider/lib/.svn/all-wcprops vendor/plugins/acts_as_attachable/.svn/all-wcprops vendor/plugins/acts_as_attachable/lib/.svn/all-wcprops vendor/plugins/acts_as_event/.svn/all-wcprops vendor/plugins/acts_as_event/lib/.svn/all-wcprops vendor/plugins/acts_as_list/.svn/all-wcprops vendor/plugins/acts_as_list/lib/.svn/all-wcprops vendor/plugins/acts_as_list/lib/active_record/.svn/all-wcprops vendor/plugins/acts_as_list/lib/active_record/acts/.svn/all-wcprops vendor/plugins/acts_as_list/test/.svn/all-wcprops vendor/plugins/acts_as_searchable/.svn/all-wcprops vendor/plugins/acts_as_searchable/lib/.svn/all-wcprops vendor/plugins/acts_as_tree/.svn/all-wcprops vendor/plugins/acts_as_tree/lib/.svn/all-wcprops vendor/plugins/acts_as_tree/lib/active_record/.svn/all-wcprops vendor/plugins/acts_as_tree/lib/active_record/acts/.svn/all-wcprops vendor/plugins/acts_as_tree/test/.svn/all-wcprops vendor/plugins/acts_as_tree/test/fixtures/.svn/all-wcprops vendor/plugins/acts_as_versioned/.svn/all-wcprops vendor/plugins/acts_as_versioned/lib/.svn/all-wcprops vendor/plugins/acts_as_versioned/test/.svn/all-wcprops vendor/plugins/acts_as_versioned/test/fixtures/.svn/all-wcprops vendor/plugins/acts_as_versioned/test/fixtures/migrations/.svn/all-wcprops vendor/plugins/acts_as_watchable/.svn/all-wcprops vendor/plugins/acts_as_watchable/lib/.svn/all-wcprops vendor/plugins/awesome_nested_set/.svn/all-wcprops vendor/plugins/awesome_nested_set/lib/.svn/all-wcprops vendor/plugins/awesome_nested_set/lib/awesome_nested_set/.svn/all-wcprops vendor/plugins/awesome_nested_set/rails/.svn/all-wcprops vendor/plugins/awesome_nested_set/test/.svn/all-wcprops vendor/plugins/awesome_nested_set/test/awesome_nested_set/.svn/all-wcprops vendor/plugins/awesome_nested_set/test/db/.svn/all-wcprops vendor/plugins/awesome_nested_set/test/fixtures/.svn/all-wcprops vendor/plugins/classic_pagination/.svn/all-wcprops vendor/plugins/classic_pagination/lib/.svn/all-wcprops vendor/plugins/classic_pagination/test/.svn/all-wcprops vendor/plugins/classic_pagination/test/fixtures/.svn/all-wcprops vendor/plugins/coderay-0.9.2/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/encoders/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/encoders/html/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/helpers/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/scanners/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/scanners/java/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/scanners/ruby/.svn/all-wcprops vendor/plugins/coderay-0.9.2/lib/coderay/styles/.svn/all-wcprops vendor/plugins/engines/.svn/all-wcprops vendor/plugins/engines/generators/.svn/all-wcprops vendor/plugins/engines/generators/plugin_migration/.svn/all-wcprops vendor/plugins/engines/generators/plugin_migration/templates/.svn/all-wcprops vendor/plugins/engines/lib/.svn/all-wcprops vendor/plugins/engines/lib/engines/.svn/all-wcprops vendor/plugins/engines/lib/engines/plugin/.svn/all-wcprops vendor/plugins/engines/lib/engines/rails_extensions/.svn/all-wcprops vendor/plugins/engines/tasks/.svn/all-wcprops vendor/plugins/engines/test/.svn/all-wcprops vendor/plugins/engines/test/app/.svn/all-wcprops vendor/plugins/engines/test/app/controllers/.svn/all-wcprops vendor/plugins/engines/test/app/controllers/namespace/.svn/all-wcprops vendor/plugins/engines/test/app/helpers/.svn/all-wcprops vendor/plugins/engines/test/app/models/.svn/all-wcprops vendor/plugins/engines/test/app/things/.svn/all-wcprops vendor/plugins/engines/test/app/views/.svn/all-wcprops vendor/plugins/engines/test/app/views/app_and_plugin/.svn/all-wcprops vendor/plugins/engines/test/app/views/namespace/.svn/all-wcprops vendor/plugins/engines/test/app/views/namespace/app_and_plugin/.svn/all-wcprops vendor/plugins/engines/test/app/views/notify_mail/.svn/all-wcprops vendor/plugins/engines/test/app/views/plugin_mail/.svn/all-wcprops vendor/plugins/engines/test/functional/.svn/all-wcprops vendor/plugins/engines/test/lib/.svn/all-wcprops vendor/plugins/engines/test/plugins/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/controllers/namespace/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/models/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/alpha_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/app_and_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/layouts/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/alpha_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/app_and_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/namespace/shared_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/app/views/shared_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/lib/.svn/all-wcprops vendor/plugins/engines/test/plugins/alpha_plugin/locales/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/controllers/namespace/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/models/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/views/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/views/namespace/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/views/namespace/shared_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/app/views/shared_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/beta_plugin/locales/.svn/all-wcprops vendor/plugins/engines/test/plugins/not_a_plugin/.svn/all-wcprops vendor/plugins/engines/test/plugins/not_a_plugin/public/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/app/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/app/controllers/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/app/views/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/app/views/assets/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/app/views/layouts/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/public/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets/public/subfolder/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets_with_assets_directory/assets/subfolder/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_assets_with_no_subdirectory/assets/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_code_mixing/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_code_mixing/app/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_code_mixing/app/things/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_load_path/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_migration/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_migration/db/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_migration/db/migrate/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_plugin_mailing/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_plugin_mailing/app/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_plugin_mailing/app/models/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_plugin_mailing/app/views/plugin_mail/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_routing/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_routing/app/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_routing/app/controllers/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_routing/app/controllers/namespace/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_routing/config/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_testing/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_testing/app/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_testing/test/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_testing/test/fixtures/.svn/all-wcprops vendor/plugins/engines/test/plugins/test_testing/test/unit/.svn/all-wcprops vendor/plugins/engines/test/unit/.svn/all-wcprops vendor/plugins/engines/test/unit/test_testing/.svn/all-wcprops vendor/plugins/gravatar/.svn/all-wcprops vendor/plugins/gravatar/lib/.svn/all-wcprops vendor/plugins/gravatar/spec/.svn/all-wcprops vendor/plugins/open_id_authentication/.svn/all-wcprops vendor/plugins/open_id_authentication/generators/.svn/all-wcprops vendor/plugins/open_id_authentication/generators/open_id_authentication_tables/.svn/all-wcprops vendor/plugins/open_id_authentication/generators/open_id_authentication_tables/templates/.svn/all-wcprops vendor/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/.svn/all-wcprops vendor/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/.svn/all-wcprops vendor/plugins/open_id_authentication/lib/.svn/all-wcprops vendor/plugins/open_id_authentication/lib/open_id_authentication/.svn/all-wcprops vendor/plugins/open_id_authentication/tasks/.svn/all-wcprops vendor/plugins/open_id_authentication/test/.svn/all-wcprops vendor/plugins/prepend_engine_views/.svn/all-wcprops vendor/plugins/rfpdf/.svn/all-wcprops vendor/plugins/rfpdf/lib/.svn/all-wcprops vendor/plugins/rfpdf/lib/rfpdf/.svn/all-wcprops vendor/plugins/rfpdf/test/.svn/all-wcprops vendor/plugins/ruby-net-ldap-0.0.4/.svn/all-wcprops vendor/plugins/ruby-net-ldap-0.0.4/lib/.svn/all-wcprops vendor/plugins/ruby-net-ldap-0.0.4/lib/net/.svn/all-wcprops vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/.svn/all-wcprops vendor/plugins/ruby-net-ldap-0.0.4/tests/.svn/all-wcprops |
diffstat | 152 files changed, 5446 insertions(+), 991 deletions(-) [+] |
line wrap: on
line diff
--- a/app/controllers/account_controller.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/controllers/account_controller.rb Thu Jan 13 13:21:03 2011 +0000 @@ -77,13 +77,19 @@ # User self-registration def register redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration] + if request.get? session[:auth_source_registration] = nil @user = User.new(:language => Setting.default_language) + + @ssamr_user_details = SsamrUserDetail.new + else @user = User.new(params[:user]) @user.admin = false + @user.register + if session[:auth_source_registration] @user.activate @user.login = session[:auth_source_registration][:login] @@ -98,6 +104,11 @@ @user.login = params[:user][:login] @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] + @ssamr_user_details = SsamrUserDetail.new(params[:ssamr_user_details]) + + # associates the 2 objects + @user.ssamr_user_detail = @ssamr_user_details + case Setting.self_registration when '1' register_by_email_activation(@user) @@ -257,6 +268,9 @@ # Pass a block for behavior when a user fails to save def register_manually_by_administrator(user, &block) if user.save + + @ssamr_user_details.save! + # Sends an email to the administrators Mailer.deliver_account_activation_request(user) account_pending
--- a/app/controllers/application_controller.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/controllers/application_controller.rb Thu Jan 13 13:21:03 2011 +0000 @@ -314,7 +314,7 @@ if api_request? logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)." end - render_error "Invalid form authenticity token." + render_error "Invalid form authenticity token. Perhaps your session has timed out; try reloading the form and entering your details again." end def render_feed(items, options={})
--- a/app/controllers/issues_controller.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/controllers/issues_controller.rb Thu Jan 13 13:21:03 2011 +0000 @@ -135,7 +135,19 @@ attachments = Attachment.attach_files(@issue, params[:attachments]) render_attachment_warning_if_needed(@issue) flash[:notice] = l(:notice_successful_create) + call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue}) + + # Adds user to watcher's list + @issue.add_watcher(User.current) + + # Also adds the assignee to the watcher's list + if params[:issue][:assigned_to_id] && !params[:issue][:assigned_to_id].empty?: + unless @issue.watcher_ids.include?(params[:issue][:assigned_to_id]): + @issue.add_watcher(User.find(params[:issue][:assigned_to_id])) + end + end + respond_to do |format| format.html { redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } : @@ -270,6 +282,18 @@ @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) @issue.init_journal(User.current, @notes) @issue.safe_attributes = params[:issue] + + # tests if the the user assigned_to_id + # is in this issues watcher's list + # if not, adds it. + + if params[:issue][:assigned_to_id] && !params[:issue][:assigned_to_id].empty?: + unless @issue.watcher_ids.include?(params[:issue][:assigned_to_id]): + @issue.add_watcher(User.find(params[:issue][:assigned_to_id])) + end + end + + end # TODO: Refactor, lots of extra code in here
--- a/app/controllers/users_controller.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/controllers/users_controller.rb Thu Jan 13 13:21:03 2011 +0000 @@ -62,6 +62,12 @@ end def show + @user = User.find(params[:id]) + + if @user.ssamr_user_detail != nil + @description = @user.ssamr_user_detail.description + end + # show projects based on current user visibility @memberships = @user.memberships.all(:conditions => Project.visible_by(User.current)) @@ -81,15 +87,19 @@ end end - def new + def new @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option) @auth_sources = AuthSource.find(:all) + + @ssamr_user_details = SsamrUserDetail.new + end verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } def create @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option) @user.safe_attributes = params[:user] + @user = User.new(params[:user]) @user.admin = params[:user][:admin] || false @user.login = params[:user][:login] @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id @@ -98,9 +108,16 @@ @user.pref.attributes = params[:pref] @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + @ssamr_user_details = SsamrUserDetail.new(params[:ssamr_user_details]) + + # associates the 2 objects + @user.ssamr_user_detail = @ssamr_user_details + if @user.save @user.pref.save - @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) + + @ssamr_user_details.save! + Mailer.deliver_account_information(@user, params[:user][:password]) if params[:send_information] @@ -127,12 +144,16 @@ end def edit + + @ssamr_user_details = @user.ssamr_user_detail + @auth_sources = AuthSource.find(:all) @membership ||= Member.new end verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } def update + @user.admin = params[:user][:admin] if params[:user][:admin] @user.login = params[:user][:login] if params[:user][:login] if params[:user][:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?) @@ -145,6 +166,21 @@ @user.pref.attributes = params[:pref] @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + if @user.ssamr_user_detail == nil + @ssamr_user_details = SsamrUserDetail.new() + @user.ssamr_user_detail = @ssamr_user_details + else + @ssamr_user_details = @user.ssamr_user_detail + end + + + if params[:ssamr_user_details].nil? or params[:ssamr_user_details].empty? + @ssamr_user_details.description = @user.ssamr_user_detail.description + else + @ssamr_user_details.description = params[:ssamr_user_details][:description] + @ssamr_user_details.save! + end + if @user.save @user.pref.save @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
--- a/app/controllers/welcome_controller.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/controllers/welcome_controller.rb Thu Jan 13 13:21:03 2011 +0000 @@ -21,6 +21,14 @@ def index @news = News.latest User.current @projects = Project.latest User.current + + # tests if user is logged in to gfenerate the tips of the day list + if User.current.logged? + @tipsoftheday = Setting.tipoftheday_text + else + @tipsoftheday = '' + end + end def robots
--- a/app/helpers/application_helper.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/helpers/application_helper.rb Thu Jan 13 13:21:03 2011 +0000 @@ -651,7 +651,7 @@ end when 'commit' if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"])) - link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision}, + link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.identifier}, :class => 'changeset', :title => truncate_single_line(changeset.comments, :length => 100) end
--- a/app/helpers/projects_helper.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/helpers/projects_helper.rb Thu Jan 13 13:21:03 2011 +0000 @@ -83,6 +83,130 @@ s end + + # Renders a tree of projects where the current user belongs + # as a nested set of unordered lists + # The given collection may be a subset of the whole project tree + # (eg. some intermediate nodes are private and can not be seen) + def render_my_project_hierarchy(projects) + s = '' + + a = '' + + # Flag to tell if user has any projects + t = FALSE + + if projects.any? + ancestors = [] + original_project = @project + projects.each do |project| + # set the project environment to please macros. + + @project = project + + if User.current.member_of?(project): + + t = TRUE + + if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) + s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n" + else + ancestors.pop + s << "</li>" + while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) + ancestors.pop + s << "</ul></li>\n" + end + end + + classes = (ancestors.empty? ? 'root' : 'child') + s << "<li class='#{classes}'><div class='#{classes}'>" + + link_to_project(project, {}, :class => "project #{User.current.member_of?(project) ? 'my-project' : nil}") + s << "<div class='wiki description'>#{textilizable(project.short_description, :project => project)}</div>" unless project.description.blank? + s << "</div>\n" + ancestors << project + end + end + s << ("</li></ul>\n" * ancestors.size) + @project = original_project + end + + if t == TRUE + a << "<h2>" + a << l("label_my_project_plural") + a << "</h2>" + a << s + else + a = s + end + + a + end + + # Renders a tree of projects where the current DOES NOT belong + # as a nested set of unordered lists + # The given collection may be a subset of the whole project tree + # (eg. some intermediate nodes are private and can not be seen) + def render_other_project_hierarchy(projects) + a = '' + s = '' + + # True if user has any projects (affects the heading used) + t = FALSE + + if projects.any? + ancestors = [] + original_project = @project + projects.each do |project| + # set the project environment to please macros. + + @project = project + + if not User.current.member_of?(project): + + if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) + s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n" + else + ancestors.pop + s << "</li>" + while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) + ancestors.pop + s << "</ul></li>\n" + end + end + + classes = (ancestors.empty? ? 'root' : 'child') + s << "<li class='#{classes}'><div class='#{classes}'>" + + link_to_project(project, {}, :class => "project #{User.current.member_of?(project) ? 'my-project' : nil}") + s << "<div class='wiki description'>#{textilizable(project.short_description, :project => project)}</div>" unless project.description.blank? + s << "</div>\n" + ancestors << project + else + t = TRUE + end + end + + s << ("</li></ul>\n" * ancestors.size) + @project = original_project + end + + if t == TRUE + a << "<h2>" + a << l("label_other_project_plural") + a << "</h2>" + a << s + else + a << "<h2>" + a << l("label_project_all") + a << "</h2>" + a << s + end + + a + end + + + # Returns a set of options for a select field, grouped by project. def version_options_for_select(versions, selected=nil) grouped = Hash.new {|h,k| h[k] = []}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/models/ssamr_user_detail.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,5 @@ +class SsamrUserDetail < ActiveRecord::Base + belongs_to :user + + validates_presence_of :description +end
--- a/app/models/user.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/app/models/user.rb Thu Jan 13 13:21:03 2011 +0000 @@ -52,6 +52,9 @@ has_one :api_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='api'" belongs_to :auth_source + has_one :ssamr_user_detail, :dependent => :destroy, :class_name => 'SsamrUserDetail' + accepts_nested_attributes_for :ssamr_user_detail + # Active non-anonymous users scope named_scope :active, :conditions => "#{User.table_name}.status = #{STATUS_ACTIVE}" @@ -63,6 +66,9 @@ attr_protected :login, :admin, :password, :password_confirmation, :hashed_password validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) } + + # TODO: is this validation correct validates_presence_of :ssamr_user_detail + validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }, :case_sensitive => false validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }, :case_sensitive => false # Login must contain lettres, numbers, underscores only @@ -94,6 +100,10 @@ write_attribute(:mail, arg.to_s.strip) end + def description=(arg) + write_attribute(:description, arg.to_s.strip) + end + def identity_url=(url) if url.blank? write_attribute(:identity_url, '')
--- a/app/views/account/register.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/account/register.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -29,6 +29,22 @@ <p><label for="user_language"><%=l(:field_language)%></label> <%= select("user", "language", lang_options_for_select) %></p> + +<h3><%=l(:label_ssamr_details)%></h3> + + <% fields_for :ssamr_user_details, :builder => TabularFormBuilder, :lang => current_language do |ssamr_user_detail| %> + <p> + + <%= ssamr_user_detail.text_area :description, :rows => 3, :cols => 40, :required => true, :class => 'wiki-edit' %> + <%= wikitoolbar_for 'ssamr_user_details_description' %> + + <em> <%=l(:text_user_ssamr_description_info)%></em> + </p> + <% end %> + + + + <% if Setting.openid? %> <p><label for="user_identity_url"><%=l(:field_identity_url)%></label> <%= text_field 'user', 'identity_url' %></p>
--- a/app/views/issues/_form.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/issues/_form.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -9,9 +9,12 @@ <p><%= f.text_field :subject, :size => 80, :required => true %></p> <% if User.current.allowed_to?(:manage_subtasks, @project) %> -<p id="parent_issue"><%= f.text_field :parent_issue_id, :size => 10 %></p> -<div id="parent_issue_candidates" class="autocomplete"></div> -<%= javascript_tag "observeParentIssueField('#{auto_complete_issues_path(:id => @issue, :project_id => @project) }')" %> + <p id="parent_issue"><%= f.text_field :parent_issue_id, :size => 10, :autocomplete => :on %> + <br /> + <em> <%=l(:text_issue_parent_issue_info)%></em> + </p> + <div id="parent_issue_candidates" class="autocomplete"></div> + <%= javascript_tag "observeParentIssueField('#{auto_complete_issues_path(:id => @issue, :project_id => @project) }')" %> <% end %> <p><%= f.text_area :description,
--- a/app/views/layouts/base.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/layouts/base.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -32,7 +32,7 @@ <%= render_menu :top_menu -%> </div> -<div id="header"> +<%= tag('div', {:id => 'header', :class => (display_main_menu?(@project) ? 'header-project' : 'header-general')}, true) %> <div id="quick-search"> <% form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %> <%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %> @@ -43,7 +43,7 @@ </div> <h1><%= page_header_title %></h1> - + <% if display_main_menu?(@project) %> <div id="main-menu"> <%= render_main_menu(@project) %>
--- a/app/views/mailer/account_activation_request.text.html.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/mailer/account_activation_request.text.html.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -1,2 +1,12 @@ <p><%= l(:mail_body_account_activation_request, h(@user.login)) %></p> <p><%= link_to @url, @url %></p> + +<h3><%= l(:label_ssamr_details) %></h3> +<p> + <%=l(:field_name)%>: <%= h @user.name %><br /> + <%=l(:field_mail)%>: <%= h @user.mail %> +</p> + +<h4><%= l(:label_ssamr_description ) %></h4> +<%= textilizable @user.ssamr_user_detail['description'] %> +
--- a/app/views/mailer/account_activation_request.text.plain.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/mailer/account_activation_request.text.plain.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -1,2 +1,11 @@ <%= l(:mail_body_account_activation_request, @user.login) %> <%= @url %> + +*<%= l(:label_ssamr_details) %>* +<%=l(:field_name)%>: <%= h @user.name %> +<%=l(:field_mail)%>: <%= h @user.mail %> + +*<%= l(:label_ssamr_description ) %>* +<%= h @user.ssamr_user_detail['description'] %> + +
--- a/app/views/projects/_form.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/projects/_form.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -2,7 +2,10 @@ <div class="box"> <!--[form:project]--> -<p><%= f.text_field :name, :required => true, :size => 60 %></p> +<p><%= f.text_field :name, :required => true, :size => 60 %> + <br /> + <em> <%= l(:text_project_name_info) %></em> +</p> <% unless @project.allowed_parents.compact.empty? %> <p><%= label(:project, :parent_id, l(:field_parent)) %><%= parent_project_select_tag(@project) %></p> @@ -11,10 +14,17 @@ <p><%= f.text_area :description, :rows => 5, :class => 'wiki-edit' %></p> <p><%= f.text_field :identifier, :required => true, :size => 60, :disabled => @project.identifier_frozen? %> <% unless @project.identifier_frozen? %> -<br /><em><%= l(:text_length_between, :min => 1, :max => Project::IDENTIFIER_MAX_LENGTH) %> <%= l(:text_project_identifier_info) %></em> + <br /> + <em><%= l(:text_length_between, :min => 1, :max => Project::IDENTIFIER_MAX_LENGTH) %> <%= l(:text_project_identifier_info) %></em> <% end %></p> -<p><%= f.text_field :homepage, :size => 60 %></p> -<p><%= f.check_box :is_public %></p> +<p><%= f.text_field :homepage, :size => 60 %> +<br /> + <em> <%= l(:text_project_homepage_info) %></em> +</p> +<p><%= f.check_box :is_public %> +<br /> + <em> <%= l(:text_project_visibility_info) %></em> +</p> <%= wikitoolbar_for 'project_description' %> <% @project.custom_field_values.each do |value| %>
--- a/app/views/projects/index.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/projects/index.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -3,22 +3,25 @@ <% end %> <div class="contextual"> - <%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %> - <%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %> - <%= link_to(l(:label_overall_spent_time), { :controller => 'time_entries' }) + ' |' if User.current.allowed_to?(:view_time_entries, nil, :global => true) %> <%= link_to l(:label_overall_activity), { :controller => 'activities', :action => 'index' }%> + <%= '| ' + link_to(l(:label_issue_view_all), { :controller => 'issues' }) if User.current.allowed_to?(:view_issues, nil, :global => true) %> + <%= '| ' + link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') if User.current.allowed_to?(:add_project, nil, :global => true) %> </div> -<h2><%=l(:label_project_plural)%></h2> +<% if User.current.logged? %> + + <%= render_my_project_hierarchy(@projects)%> -<%= render_project_hierarchy(@projects)%> + <%= render_other_project_hierarchy(@projects)%> -<% if User.current.logged? %> -<p style="text-align:right;"> -<span class="my-project"><%= l(:label_my_projects) %></span> -</p> +<% else %> + + <h2><%=l(:label_project_plural)%></h2> + <%= render_project_hierarchy(@projects)%> <% end %> + + <% other_formats_links do |f| %> <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> <% end %>
--- a/app/views/projects/settings/_members.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/projects/settings/_members.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -13,19 +13,18 @@ </tr></thead> <tbody> <% members.each do |member| %> - <% next if member.new_record? %> - <tr id="member-<%= member.id %>" class="<%= cycle 'odd', 'even' %> member"> - <td class="<%= member.principal.class.name.downcase %>"><%= link_to_user member.principal %></td> - <td class="roles"> - <span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> - <% if authorize_for('members', 'edit') %> - <% remote_form_for(:member, member, :url => {:controller => 'members', :action => 'edit', :id => member}, - :method => :post, - :html => { :id => "member-#{member.id}-roles-form", :class => 'hol' }) do |f| %> - <p><% roles.each do |role| %> - <label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), + <% next if member.new_record? %> + <tr id="member-<%= member.id %>" class="<%= cycle 'odd', 'even' %> member"> + <td class="<%= member.principal.class.name.downcase %>"><%= link_to_user member.principal %></td> + <td class="roles"> + <span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> + <% if authorize_for('members', 'edit') %> + <% remote_form_for(:member, member, :url => {:controller => 'members', :action => 'edit', :id => member}, + :method => :post, :html => { :id => "member-#{member.id}-roles-form", :class => 'hol' }) do |f| %> + <p><% roles.each do |role| %> + <label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), :disabled => member.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?} %> <%=h role %></label><br /> - <% end %></p> + <% end %></p> <%= hidden_field_tag 'member[role_ids][]', '' %> <p><%= submit_tag l(:button_change), :class => "small" %> <%= link_to_function l(:button_cancel), "$('member-#{member.id}-roles').show(); $('member-#{member.id}-roles-form').hide(); return false;" %></p> @@ -51,7 +50,7 @@ </div> -<% principals = Principal.active.find(:all, :limit => 100, :order => 'type, login, lastname ASC') - @project.principals %> +<% principals = Principal.active.find(:all, :limit => 10, :order => 'type, login, lastname ASC') - @project.principals %> <div class="splitcontentright"> <% if roles.any? && principals.any? %>
--- a/app/views/projects/settings/_repository.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/projects/settings/_repository.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -6,6 +6,9 @@ <%= error_messages_for 'repository' %> <div class="box tabular"> +<% if !@repository || !@repository.url %> +<ul><li>The repository for a project will normally be set up automatically within a few minutes of the project being created.</li></ul> +<% end %> <p><%= label_tag('repository_scm', l(:label_scm)) %><%= scm_select_tag(@repository) %></p> <%= repository_field_tags(f, @repository) if @repository %> </div>
--- a/app/views/repositories/_dir_list_content.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/repositories/_dir_list_content.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -16,7 +16,7 @@ :class => (entry.is_dir? ? 'icon icon-folder' : "icon icon-file #{Redmine::MimeType.css_class_of(entry.name)}")%> </td> <td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td> -<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %> +<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier.to_s) if entry.lastrev && entry.lastrev.identifier %> <td class="revision"><%= link_to_revision(changeset, @project) if changeset %></td> <td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td> <td class="author"><%= changeset.nil? ? h(entry.lastrev.author.to_s.split('<').first) : changeset.author if entry.lastrev %></td>
--- a/app/views/settings/_general.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/settings/_general.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -3,9 +3,15 @@ <div class="box tabular settings"> <p><%= setting_text_field :app_title, :size => 30 %></p> +<p><%= setting_text_area :notifications_text, :cols => 60, :rows => 5, :class => 'wiki-edit' %></p> + <%= wikitoolbar_for 'settings_notifications_text' %> + <p><%= setting_text_area :welcome_text, :cols => 60, :rows => 5, :class => 'wiki-edit' %></p> <%= wikitoolbar_for 'settings_welcome_text' %> +<p><%= setting_text_area :tipoftheday_text, :cols => 60, :rows => 5, :class => 'wiki-edit' %></p> + <%= wikitoolbar_for 'settings_tipoftheday_text' %> + <p><%= setting_text_field :attachment_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p> <p><%= setting_text_field :per_page_options, :size => 20 %><br />
--- a/app/views/users/_form.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/users/_form.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -20,6 +20,20 @@ </div> <div class="box tabular"> + <h3><%=l(:label_ssamr_details)%></h3> + <% fields_for :ssamr_user_details, :builder => TabularFormBuilder, :lang => current_language do |ssamr_user_detail| %> + <p> + <%= ssamr_user_detail.text_area :description, :rows => 3, :cols => 40, :required => true, :class => 'wiki-edit' %> + <%= wikitoolbar_for 'ssamr_user_details_description' %> + <br /> + <em> <%=l(:text_user_ssamr_description_info)%></em> + </p> + <% end %> +</div> + + + +<div class="box tabular"> <h3><%=l(:label_authentication)%></h3> <% unless @auth_sources.empty? %> <p><%= f.select :auth_source_id, ([[l(:label_internal), ""]] + @auth_sources.collect { |a| [a.name, a.id] }), {}, :onchange => "if (this.value=='') {Element.show('password_fields');} else {Element.hide('password_fields');}" %></p>
--- a/app/views/users/show.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/users/show.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -20,6 +20,10 @@ <% end %> </ul> +<h3><%=l(:label_ssamr_description)%></h3> +<%= textilizable @description %> + + <% unless @memberships.empty? %> <h3><%=l(:label_project_plural)%></h3> <ul>
--- a/app/views/welcome/index.rhtml Thu Jan 13 12:53:21 2011 +0000 +++ b/app/views/welcome/index.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -1,7 +1,22 @@ -<h2><%= l(:label_home) %></h2> +<% if not Setting.notifications_text.empty? %> + <div class="notifications flash error"> + <%= textilizable Setting.notifications_text %> + </div> +<% end %> + +<h2><%= l(:label_home_heading) %></h2> <div class="splitcontentleft"> <%= textilizable Setting.welcome_text %> + + <% if not @tipsoftheday.empty? %> + <div class="newsoftheday box"> + <h3><%=l(:label_tipoftheday)%></h3> + <%= textilizable @tipsoftheday %> + </div> + <% end %> + + <% if @news.any? %> <div class="news box"> <h3><%=l(:label_news_latest)%></h3>
--- a/config/locales/bg.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/bg.yml Thu Jan 13 13:21:03 2011 +0000 @@ -312,6 +312,7 @@ label_register: Регистрация label_password_lost: Забравена парола label_home: Начало + label_home_heading: Начало label_my_page: Лична страница label_my_account: Профил label_my_projects: Проекти, в които участвам
--- a/config/locales/bs.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/bs.yml Thu Jan 13 13:21:03 2011 +0000 @@ -439,6 +439,7 @@ label_login_with_open_id_option: ili prijava sa OpenID-om label_password_lost: Izgubljena lozinka label_home: Početna stranica + label_home_heading: Početna stranica label_my_page: Moja stranica label_my_account: Moj korisnički račun label_my_projects: Moji projekti
--- a/config/locales/ca.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/ca.yml Thu Jan 13 13:21:03 2011 +0000 @@ -475,6 +475,7 @@ label_login_with_open_id_option: "o entra amb l'OpenID" label_password_lost: Contrasenya perduda label_home: Inici + label_home_heading: Inici label_my_page: La meva pàgina label_my_account: El meu compte label_my_projects: Els meus projectes
--- a/config/locales/cs.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/cs.yml Thu Jan 13 13:21:03 2011 +0000 @@ -357,6 +357,7 @@ label_register: Registrovat label_password_lost: Zapomenuté heslo label_home: Úvodní + label_home_heading: Úvodní label_my_page: Moje stránka label_my_account: Můj účet label_my_projects: Moje projekty
--- a/config/locales/da.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/da.yml Thu Jan 13 13:21:03 2011 +0000 @@ -365,6 +365,7 @@ label_register: Registrér label_password_lost: Glemt kodeord label_home: Forside + label_home_heading: Forside label_my_page: Min side label_my_account: Min konto label_my_projects: Mine projekter
--- a/config/locales/de.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/de.yml Thu Jan 13 13:21:03 2011 +0000 @@ -489,6 +489,7 @@ label_login_with_open_id_option: oder mit OpenID anmelden label_password_lost: Kennwort vergessen label_home: Hauptseite + label_home_heading: Hauptseite label_my_page: Meine Seite label_my_account: Mein Konto label_my_projects: Meine Projekte
--- a/config/locales/el.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/el.yml Thu Jan 13 13:21:03 2011 +0000 @@ -437,6 +437,7 @@ label_login_with_open_id_option: ή συνδεθείτε με OpenID label_password_lost: Ανάκτηση κωδικού πρόσβασης label_home: Αρχική σελίδα + label_home_heading: Αρχική σελίδα label_my_page: Η σελίδα μου label_my_account: Ο λογαριασμός μου label_my_projects: Τα έργα μου
--- a/config/locales/en-GB.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/en-GB.yml Thu Jan 13 13:21:03 2011 +0000 @@ -1,942 +1,956 @@ -en-GB: - direction: ltr - date: - formats: - # Use the strftime parameters for formats. - # When no format has been given, it uses default. - # You can provide other formats here if you like! - default: "%d/%m/%Y" - short: "%d %b" - long: "%d %B, %Y" - - day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] - abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat] - - # Don't forget the nil at the beginning; there's no such thing as a 0th month - month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December] - abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec] - # Used in date_select and datime_select. - order: [ :year, :month, :day ] - - time: - formats: - default: "%d/%m/%Y %I:%M %p" - time: "%I:%M %p" - short: "%d %b %H:%M" - long: "%d %B, %Y %H:%M" - am: "am" - pm: "pm" - - datetime: - distance_in_words: - half_a_minute: "half a minute" - less_than_x_seconds: - one: "less than 1 second" - other: "less than %{count} seconds" - x_seconds: - one: "1 second" - other: "%{count} seconds" - less_than_x_minutes: - one: "less than a minute" - other: "less than %{count} minutes" - x_minutes: - one: "1 minute" - other: "%{count} minutes" - about_x_hours: - one: "about 1 hour" - other: "about %{count} hours" - x_days: - one: "1 day" - other: "%{count} days" - about_x_months: - one: "about 1 month" - other: "about %{count} months" - x_months: - one: "1 month" - other: "%{count} months" - about_x_years: - one: "about 1 year" - other: "about %{count} years" - over_x_years: - one: "over 1 year" - other: "over %{count} years" - almost_x_years: - one: "almost 1 year" - other: "almost %{count} years" - - number: - format: - separator: "." - delimiter: " " - precision: 3 - - currency: - format: - format: "%u%n" - unit: "£" - human: - format: - delimiter: "" - precision: 1 - storage_units: - format: "%n %u" - units: - byte: - one: "Byte" - other: "Bytes" - kb: "kB" - mb: "MB" - gb: "GB" - tb: "TB" - - -# Used in array.to_sentence. - support: - array: - sentence_connector: "and" - skip_last_comma: false - - activerecord: - errors: - template: - header: - one: "1 error prohibited this %{model} from being saved" - other: "%{count} errors prohibited this %{model} from being saved" - messages: - inclusion: "is not included in the list" - exclusion: "is reserved" - invalid: "is invalid" - confirmation: "doesn't match confirmation" - accepted: "must be accepted" - empty: "can't be empty" - blank: "can't be blank" - too_long: "is too long (maximum is %{count} characters)" - too_short: "is too short (minimum is %{count} characters)" - wrong_length: "is the wrong length (should be %{count} characters)" - taken: "has already been taken" - not_a_number: "is not a number" - not_a_date: "is not a valid date" - greater_than: "must be greater than %{count}" - greater_than_or_equal_to: "must be greater than or equal to %{count}" - equal_to: "must be equal to %{count}" - less_than: "must be less than %{count}" - less_than_or_equal_to: "must be less than or equal to %{count}" - odd: "must be odd" - even: "must be even" - greater_than_start_date: "must be greater than start date" - not_same_project: "doesn't belong to the same project" - circular_dependency: "This relation would create a circular dependency" - cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" - - actionview_instancetag_blank_option: Please select - - general_text_No: 'No' - general_text_Yes: 'Yes' - general_text_no: 'no' - general_text_yes: 'yes' - general_lang_name: 'English (British)' - general_csv_separator: ',' - general_csv_decimal_separator: '.' - general_csv_encoding: ISO-8859-1 - general_pdf_encoding: ISO-8859-1 - general_first_day_of_week: '1' - - notice_account_updated: Account was successfully updated. - notice_account_invalid_creditentials: Invalid user or password - notice_account_password_updated: Password was successfully updated. - notice_account_wrong_password: Wrong password - notice_account_register_done: Account was successfully created. To activate your account, click on the link that was emailed to you. - notice_account_unknown_email: Unknown user. - notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password. - notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you. - notice_account_activated: Your account has been activated. You can now log in. - notice_successful_create: Successful creation. - notice_successful_update: Successful update. - notice_successful_delete: Successful deletion. - notice_successful_connection: Successful connection. - notice_file_not_found: The page you were trying to access doesn't exist or has been removed. - notice_locking_conflict: Data has been updated by another user. - notice_not_authorized: You are not authorised to access this page. - notice_email_sent: "An email was sent to %{value}" - notice_email_error: "An error occurred while sending mail (%{value})" - notice_feeds_access_key_reseted: Your RSS access key was reset. - notice_api_access_key_reseted: Your API access key was reset. - notice_failed_to_save_issues: "Failed to save %{count} issue(s) on %{total} selected: %{ids}." - notice_no_issue_selected: "No issue is selected! Please, check the issues you want to edit." - notice_account_pending: "Your account was created and is now pending administrator approval." - notice_default_data_loaded: Default configuration successfully loaded. - notice_unable_delete_version: Unable to delete version. - notice_issue_done_ratios_updated: Issue done ratios updated. - - error_can_t_load_default_data: "Default configuration could not be loaded: %{value}" - error_scm_not_found: "The entry or revision was not found in the repository." - error_scm_command_failed: "An error occurred when trying to access the repository: %{value}" - error_scm_annotate: "The entry does not exist or can not be annotated." - error_issue_not_found_in_project: 'The issue was not found or does not belong to this project' - error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.' - error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").' - error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version can not be reopened' - error_can_not_archive_project: This project can not be archived - error_issue_done_ratios_not_updated: "Issue done ratios not updated." - error_workflow_copy_source: 'Please select a source tracker or role' - error_workflow_copy_target: 'Please select target tracker(s) and role(s)' - - warning_attachments_not_saved: "%{count} file(s) could not be saved." - - mail_subject_lost_password: "Your %{value} password" - mail_body_lost_password: 'To change your password, click on the following link:' - mail_subject_register: "Your %{value} account activation" - mail_body_register: 'To activate your account, click on the following link:' - mail_body_account_information_external: "You can use your %{value} account to log in." - mail_body_account_information: Your account information - mail_subject_account_activation_request: "%{value} account activation request" - mail_body_account_activation_request: "A new user (%{value}) has registered. The account is pending your approval:" - mail_subject_reminder: "%{count} issue(s) due in the next %{days} days" - mail_body_reminder: "%{count} issue(s) that are assigned to you are due in the next %{days} days:" - mail_subject_wiki_content_added: "'%{id}' wiki page has been added" - mail_body_wiki_content_added: "The '%{id}' wiki page has been added by %{author}." - mail_subject_wiki_content_updated: "'%{id}' wiki page has been updated" - mail_body_wiki_content_updated: "The '%{id}' wiki page has been updated by %{author}." - - gui_validation_error: 1 error - gui_validation_error_plural: "%{count} errors" - - field_name: Name - field_description: Description - field_summary: Summary - field_is_required: Required - field_firstname: Firstname - field_lastname: Lastname - field_mail: Email - field_filename: File - field_filesize: Size - field_downloads: Downloads - field_author: Author - field_created_on: Created - field_updated_on: Updated - field_field_format: Format - field_is_for_all: For all projects - field_possible_values: Possible values - field_regexp: Regular expression - field_min_length: Minimum length - field_max_length: Maximum length - field_value: Value - field_category: Category - field_title: Title - field_project: Project - field_issue: Issue - field_status: Status - field_notes: Notes - field_is_closed: Issue closed - field_is_default: Default value - field_tracker: Tracker - field_subject: Subject - field_due_date: Due date - field_assigned_to: Assignee - field_priority: Priority - field_fixed_version: Target version - field_user: User - field_role: Role - field_homepage: Homepage - field_is_public: Public - field_parent: Subproject of - field_is_in_roadmap: Issues displayed in roadmap - field_login: Login - field_mail_notification: Email notifications - field_admin: Administrator - field_last_login_on: Last connection - field_language: Language - field_effective_date: Date - field_password: Password - field_new_password: New password - field_password_confirmation: Confirmation - field_version: Version - field_type: Type - field_host: Host - field_port: Port - field_account: Account - field_base_dn: Base DN - field_attr_login: Login attribute - field_attr_firstname: Firstname attribute - field_attr_lastname: Lastname attribute - field_attr_mail: Email attribute - field_onthefly: On-the-fly user creation - field_start_date: Start date - field_done_ratio: % Done - field_auth_source: Authentication mode - field_hide_mail: Hide my email address - field_comments: Comment - field_url: URL - field_start_page: Start page - field_subproject: Subproject - field_hours: Hours - field_activity: Activity - field_spent_on: Date - field_identifier: Identifier - field_is_filter: Used as a filter - field_issue_to: Related issue - field_delay: Delay - field_assignable: Issues can be assigned to this role - field_redirect_existing_links: Redirect existing links - field_estimated_hours: Estimated time - field_column_names: Columns - field_time_zone: Time zone - field_searchable: Searchable - field_default_value: Default value - field_comments_sorting: Display comments - field_parent_title: Parent page - field_editable: Editable - field_watcher: Watcher - field_identity_url: OpenID URL - field_content: Content - field_group_by: Group results by - field_sharing: Sharing - - setting_app_title: Application title - setting_app_subtitle: Application subtitle - setting_welcome_text: Welcome text - setting_default_language: Default language - setting_login_required: Authentication required - setting_self_registration: Self-registration - setting_attachment_max_size: Attachment max. size - setting_issues_export_limit: Issues export limit - setting_mail_from: Emission email address - setting_bcc_recipients: Blind carbon copy recipients (bcc) - setting_plain_text_mail: Plain text mail (no HTML) - setting_host_name: Host name and path - setting_text_formatting: Text formatting - setting_wiki_compression: Wiki history compression - setting_feeds_limit: Feed content limit - setting_default_projects_public: New projects are public by default - setting_autofetch_changesets: Autofetch commits - setting_sys_api_enabled: Enable WS for repository management - setting_commit_ref_keywords: Referencing keywords - setting_commit_fix_keywords: Fixing keywords - setting_autologin: Autologin - setting_date_format: Date format - setting_time_format: Time format - setting_cross_project_issue_relations: Allow cross-project issue relations - setting_issue_list_default_columns: Default columns displayed on the issue list - setting_repositories_encodings: Repositories encodings - setting_commit_logs_encoding: Commit messages encoding - setting_emails_footer: Emails footer - setting_protocol: Protocol - setting_per_page_options: Objects per page options - setting_user_format: Users display format - setting_activity_days_default: Days displayed on project activity - setting_display_subprojects_issues: Display subprojects issues on main projects by default - setting_enabled_scm: Enabled SCM - setting_mail_handler_body_delimiters: "Truncate emails after one of these lines" - setting_mail_handler_api_enabled: Enable WS for incoming emails - setting_mail_handler_api_key: API key - setting_sequential_project_identifiers: Generate sequential project identifiers - setting_gravatar_enabled: Use Gravatar user icons - setting_gravatar_default: Default Gravatar image - setting_diff_max_lines_displayed: Max number of diff lines displayed - setting_file_max_size_displayed: Max size of text files displayed inline - setting_repository_log_display_limit: Maximum number of revisions displayed on file log - setting_openid: Allow OpenID login and registration - setting_password_min_length: Minimum password length - setting_new_project_user_role_id: Role given to a non-admin user who creates a project - setting_default_projects_modules: Default enabled modules for new projects - setting_issue_done_ratio: Calculate the issue done ratio with - setting_issue_done_ratio_issue_field: Use the issue field - setting_issue_done_ratio_issue_status: Use the issue status - setting_start_of_week: Start calendars on - setting_rest_api_enabled: Enable REST web service - setting_cache_formatted_text: Cache formatted text - - permission_add_project: Create project - permission_add_subprojects: Create subprojects - permission_edit_project: Edit project - permission_select_project_modules: Select project modules - permission_manage_members: Manage members - permission_manage_project_activities: Manage project activities - permission_manage_versions: Manage versions - permission_manage_categories: Manage issue categories - permission_view_issues: View Issues - permission_add_issues: Add issues - permission_edit_issues: Edit issues - permission_manage_issue_relations: Manage issue relations - permission_add_issue_notes: Add notes - permission_edit_issue_notes: Edit notes - permission_edit_own_issue_notes: Edit own notes - permission_move_issues: Move issues - permission_delete_issues: Delete issues - permission_manage_public_queries: Manage public queries - permission_save_queries: Save queries - permission_view_gantt: View gantt chart - permission_view_calendar: View calendar - permission_view_issue_watchers: View watchers list - permission_add_issue_watchers: Add watchers - permission_delete_issue_watchers: Delete watchers - permission_log_time: Log spent time - permission_view_time_entries: View spent time - permission_edit_time_entries: Edit time logs - permission_edit_own_time_entries: Edit own time logs - permission_manage_news: Manage news - permission_comment_news: Comment news - permission_manage_documents: Manage documents - permission_view_documents: View documents - permission_manage_files: Manage files - permission_view_files: View files - permission_manage_wiki: Manage wiki - permission_rename_wiki_pages: Rename wiki pages - permission_delete_wiki_pages: Delete wiki pages - permission_view_wiki_pages: View wiki - permission_view_wiki_edits: View wiki history - permission_edit_wiki_pages: Edit wiki pages - permission_delete_wiki_pages_attachments: Delete attachments - permission_protect_wiki_pages: Protect wiki pages - permission_manage_repository: Manage repository - permission_browse_repository: Browse repository - permission_view_changesets: View changesets - permission_commit_access: Commit access - permission_manage_boards: Manage boards - permission_view_messages: View messages - permission_add_messages: Post messages - permission_edit_messages: Edit messages - permission_edit_own_messages: Edit own messages - permission_delete_messages: Delete messages - permission_delete_own_messages: Delete own messages - permission_export_wiki_pages: Export wiki pages - - project_module_issue_tracking: Issue tracking - project_module_time_tracking: Time tracking - project_module_news: News - project_module_documents: Documents - project_module_files: Files - project_module_wiki: Wiki - project_module_repository: Repository - project_module_boards: Boards - - label_user: User - label_user_plural: Users - label_user_new: New user - label_user_anonymous: Anonymous - label_project: Project - label_project_new: New project - label_project_plural: Projects - label_x_projects: - zero: no projects - one: 1 project - other: "%{count} projects" - label_project_all: All Projects - label_project_latest: Latest projects - label_issue: Issue - label_issue_new: New issue - label_issue_plural: Issues - label_issue_view_all: View all issues - label_issues_by: "Issues by %{value}" - label_issue_added: Issue added - label_issue_updated: Issue updated - label_document: Document - label_document_new: New document - label_document_plural: Documents - label_document_added: Document added - label_role: Role - label_role_plural: Roles - label_role_new: New role - label_role_and_permissions: Roles and permissions - label_member: Member - label_member_new: New member - label_member_plural: Members - label_tracker: Tracker - label_tracker_plural: Trackers - label_tracker_new: New tracker - label_workflow: Workflow - label_issue_status: Issue status - label_issue_status_plural: Issue statuses - label_issue_status_new: New status - label_issue_category: Issue category - label_issue_category_plural: Issue categories - label_issue_category_new: New category - label_custom_field: Custom field - label_custom_field_plural: Custom fields - label_custom_field_new: New custom field - label_enumerations: Enumerations - label_enumeration_new: New value - label_information: Information - label_information_plural: Information - label_please_login: Please log in - label_register: Register - label_login_with_open_id_option: or login with OpenID - label_password_lost: Lost password - label_home: Home - label_my_page: My page - label_my_account: My account - label_my_projects: My projects - label_administration: Administration - label_login: Sign in - label_logout: Sign out - label_help: Help - label_reported_issues: Reported issues - label_assigned_to_me_issues: Issues assigned to me - label_last_login: Last connection - label_registered_on: Registered on - label_activity: Activity - label_overall_activity: Overall activity - label_user_activity: "%{value}'s activity" - label_new: New - label_logged_as: Logged in as - label_environment: Environment - label_authentication: Authentication - label_auth_source: Authentication mode - label_auth_source_new: New authentication mode - label_auth_source_plural: Authentication modes - label_subproject_plural: Subprojects - label_subproject_new: New subproject - label_and_its_subprojects: "%{value} and its subprojects" - label_min_max_length: Min - Max length - label_list: List - label_date: Date - label_integer: Integer - label_float: Float - label_boolean: Boolean - label_string: Text - label_text: Long text - label_attribute: Attribute - label_attribute_plural: Attributes - label_download: "%{count} Download" - label_download_plural: "%{count} Downloads" - label_no_data: No data to display - label_change_status: Change status - label_history: History - label_attachment: File - label_attachment_new: New file - label_attachment_delete: Delete file - label_attachment_plural: Files - label_file_added: File added - label_report: Report - label_report_plural: Reports - label_news: News - label_news_new: Add news - label_news_plural: News - label_news_latest: Latest news - label_news_view_all: View all news - label_news_added: News added - label_settings: Settings - label_overview: Overview - label_version: Version - label_version_new: New version - label_version_plural: Versions - label_close_versions: Close completed versions - label_confirmation: Confirmation - label_export_to: 'Also available in:' - label_read: Read... - label_public_projects: Public projects - label_open_issues: open - label_open_issues_plural: open - label_closed_issues: closed - label_closed_issues_plural: closed - label_x_open_issues_abbr_on_total: - zero: 0 open / %{total} - one: 1 open / %{total} - other: "%{count} open / %{total}" - label_x_open_issues_abbr: - zero: 0 open - one: 1 open - other: "%{count} open" - label_x_closed_issues_abbr: - zero: 0 closed - one: 1 closed - other: "%{count} closed" - label_total: Total - label_permissions: Permissions - label_current_status: Current status - label_new_statuses_allowed: New statuses allowed - label_all: all - label_none: none - label_nobody: nobody - label_next: Next - label_previous: Previous - label_used_by: Used by - label_details: Details - label_add_note: Add a note - label_per_page: Per page - label_calendar: Calendar - label_months_from: months from - label_gantt: Gantt - label_internal: Internal - label_last_changes: "last %{count} changes" - label_change_view_all: View all changes - label_personalize_page: Personalise this page - label_comment: Comment - label_comment_plural: Comments - label_x_comments: - zero: no comments - one: 1 comment - other: "%{count} comments" - label_comment_add: Add a comment - label_comment_added: Comment added - label_comment_delete: Delete comments - label_query: Custom query - label_query_plural: Custom queries - label_query_new: New query - label_filter_add: Add filter - label_filter_plural: Filters - label_equals: is - label_not_equals: is not - label_in_less_than: in less than - label_in_more_than: in more than - label_greater_or_equal: '>=' - label_less_or_equal: '<=' - label_in: in - label_today: today - label_all_time: all time - label_yesterday: yesterday - label_this_week: this week - label_last_week: last week - label_last_n_days: "last %{count} days" - label_this_month: this month - label_last_month: last month - label_this_year: this year - label_date_range: Date range - label_less_than_ago: less than days ago - label_more_than_ago: more than days ago - label_ago: days ago - label_contains: contains - label_not_contains: doesn't contain - label_day_plural: days - label_repository: Repository - label_repository_plural: Repositories - label_browse: Browse - label_modification: "%{count} change" - label_modification_plural: "%{count} changes" - label_branch: Branch - label_tag: Tag - label_revision: Revision - label_revision_plural: Revisions - label_revision_id: "Revision %{value}" - label_associated_revisions: Associated revisions - label_added: added - label_modified: modified - label_copied: copied - label_renamed: renamed - label_deleted: deleted - label_latest_revision: Latest revision - label_latest_revision_plural: Latest revisions - label_view_revisions: View revisions - label_view_all_revisions: View all revisions - label_max_size: Maximum size - label_sort_highest: Move to top - label_sort_higher: Move up - label_sort_lower: Move down - label_sort_lowest: Move to bottom - label_roadmap: Roadmap - label_roadmap_due_in: "Due in %{value}" - label_roadmap_overdue: "%{value} late" - label_roadmap_no_issues: No issues for this version - label_search: Search - label_result_plural: Results - label_all_words: All words - label_wiki: Wiki - label_wiki_edit: Wiki edit - label_wiki_edit_plural: Wiki edits - label_wiki_page: Wiki page - label_wiki_page_plural: Wiki pages - label_index_by_title: Index by title - label_index_by_date: Index by date - label_current_version: Current version - label_preview: Preview - label_feed_plural: Feeds - label_changes_details: Details of all changes - label_issue_tracking: Issue tracking - label_spent_time: Spent time - label_f_hour: "%{value} hour" - label_f_hour_plural: "%{value} hours" - label_time_tracking: Time tracking - label_change_plural: Changes - label_statistics: Statistics - label_commits_per_month: Commits per month - label_commits_per_author: Commits per author - label_view_diff: View differences - label_diff_inline: inline - label_diff_side_by_side: side by side - label_options: Options - label_copy_workflow_from: Copy workflow from - label_permissions_report: Permissions report - label_watched_issues: Watched issues - label_related_issues: Related issues - label_applied_status: Applied status - label_loading: Loading... - label_relation_new: New relation - label_relation_delete: Delete relation - label_relates_to: related to - label_duplicates: duplicates - label_duplicated_by: duplicated by - label_blocks: blocks - label_blocked_by: blocked by - label_precedes: precedes - label_follows: follows - label_end_to_start: end to start - label_end_to_end: end to end - label_start_to_start: start to start - label_start_to_end: start to end - label_stay_logged_in: Stay logged in - label_disabled: disabled - label_show_completed_versions: Show completed versions - label_me: me - label_board: Forum - label_board_new: New forum - label_board_plural: Forums - label_board_locked: Locked - label_board_sticky: Sticky - label_topic_plural: Topics - label_message_plural: Messages - label_message_last: Last message - label_message_new: New message - label_message_posted: Message added - label_reply_plural: Replies - label_send_information: Send account information to the user - label_year: Year - label_month: Month - label_week: Week - label_date_from: From - label_date_to: To - label_language_based: Based on user's language - label_sort_by: "Sort by %{value}" - label_send_test_email: Send a test email - label_feeds_access_key: RSS access key - label_missing_feeds_access_key: Missing a RSS access key - label_feeds_access_key_created_on: "RSS access key created %{value} ago" - label_module_plural: Modules - label_added_time_by: "Added by %{author} %{age} ago" - label_updated_time_by: "Updated by %{author} %{age} ago" - label_updated_time: "Updated %{value} ago" - label_jump_to_a_project: Jump to a project... - label_file_plural: Files - label_changeset_plural: Changesets - label_default_columns: Default columns - label_no_change_option: (No change) - label_bulk_edit_selected_issues: Bulk edit selected issues - label_theme: Theme - label_default: Default - label_search_titles_only: Search titles only - label_user_mail_option_all: "For any event on all my projects" - label_user_mail_option_selected: "For any event on the selected projects only..." - label_user_mail_option_none: "No events" - label_user_mail_no_self_notified: "I don't want to be notified of changes that I make myself" - label_registration_activation_by_email: account activation by email - label_registration_manual_activation: manual account activation - label_registration_automatic_activation: automatic account activation - label_display_per_page: "Per page: %{value}" - label_age: Age - label_change_properties: Change properties - label_general: General - label_more: More - label_scm: SCM - label_plugins: Plugins - label_ldap_authentication: LDAP authentication - label_downloads_abbr: D/L - label_optional_description: Optional description - label_add_another_file: Add another file - label_preferences: Preferences - label_chronological_order: In chronological order - label_reverse_chronological_order: In reverse chronological order - label_planning: Planning - label_incoming_emails: Incoming emails - label_generate_key: Generate a key - label_issue_watchers: Watchers - label_example: Example - label_display: Display - label_sort: Sort - label_ascending: Ascending - label_descending: Descending - label_date_from_to: From %{start} to %{end} - label_wiki_content_added: Wiki page added - label_wiki_content_updated: Wiki page updated - label_group: Group - label_group_plural: Groups - label_group_new: New group - label_time_entry_plural: Spent time - label_version_sharing_none: Not shared - label_version_sharing_descendants: With subprojects - label_version_sharing_hierarchy: With project hierarchy - label_version_sharing_tree: With project tree - label_version_sharing_system: With all projects - label_update_issue_done_ratios: Update issue done ratios - label_copy_source: Source - label_copy_target: Target - label_copy_same_as_target: Same as target - label_display_used_statuses_only: Only display statuses that are used by this tracker - label_api_access_key: API access key - label_missing_api_access_key: Missing an API access key - label_api_access_key_created_on: "API access key created %{value} ago" - - button_login: Login - button_submit: Submit - button_save: Save - button_check_all: Check all - button_uncheck_all: Uncheck all - button_delete: Delete - button_create: Create - button_create_and_continue: Create and continue - button_test: Test - button_edit: Edit - button_add: Add - button_change: Change - button_apply: Apply - button_clear: Clear - button_lock: Lock - button_unlock: Unlock - button_download: Download - button_list: List - button_view: View - button_move: Move - button_move_and_follow: Move and follow - button_back: Back - button_cancel: Cancel - button_activate: Activate - button_sort: Sort - button_log_time: Log time - button_rollback: Rollback to this version - button_watch: Watch - button_unwatch: Unwatch - button_reply: Reply - button_archive: Archive - button_unarchive: Unarchive - button_reset: Reset - button_rename: Rename - button_change_password: Change password - button_copy: Copy - button_copy_and_follow: Copy and follow - button_annotate: Annotate - button_update: Update - button_configure: Configure - button_quote: Quote - button_duplicate: Duplicate - button_show: Show - - status_active: active - status_registered: registered - status_locked: locked - - version_status_open: open - version_status_locked: locked - version_status_closed: closed - - field_active: Active - - text_select_mail_notifications: Select actions for which email notifications should be sent. - text_regexp_info: eg. ^[A-Z0-9]+$ - text_min_max_length_info: 0 means no restriction - text_project_destroy_confirmation: Are you sure you want to delete this project and related data? - text_subprojects_destroy_warning: "Its subproject(s): %{value} will be also deleted." - text_workflow_edit: Select a role and a tracker to edit the workflow - text_are_you_sure: Are you sure? - text_journal_changed: "%{label} changed from %{old} to %{new}" - text_journal_set_to: "%{label} set to %{value}" - text_journal_deleted: "%{label} deleted (%{old})" - text_journal_added: "%{label} %{value} added" - text_tip_issue_begin_day: task beginning this day - text_tip_issue_end_day: task ending this day - text_tip_issue_begin_end_day: task beginning and ending this day - text_project_identifier_info: 'Only lower case letters (a-z), numbers and dashes are allowed.<br />Once saved, the identifier can not be changed.' - text_caracters_maximum: "%{count} characters maximum." - text_caracters_minimum: "Must be at least %{count} characters long." - text_length_between: "Length between %{min} and %{max} characters." - text_tracker_no_workflow: No workflow defined for this tracker - text_unallowed_characters: Unallowed characters - text_comma_separated: Multiple values allowed (comma separated). - text_line_separated: Multiple values allowed (one line for each value). - text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages - text_issue_added: "Issue %{id} has been reported by %{author}." - text_issue_updated: "Issue %{id} has been updated by %{author}." - text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and all its content? - text_issue_category_destroy_question: "Some issues (%{count}) are assigned to this category. What do you want to do?" - text_issue_category_destroy_assignments: Remove category assignments - text_issue_category_reassign_to: Reassign issues to this category - text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)." - text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded." - text_load_default_configuration: Load the default configuration - text_status_changed_by_changeset: "Applied in changeset %{value}." - text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?' - text_select_project_modules: 'Select modules to enable for this project:' - text_default_administrator_account_changed: Default administrator account changed - text_file_repository_writable: Attachments directory writable - text_plugin_assets_writable: Plugin assets directory writable - text_rmagick_available: RMagick available (optional) - text_destroy_time_entries_question: "%{hours} hours were reported on the issues you are about to delete. What do you want to do?" - text_destroy_time_entries: Delete reported hours - text_assign_time_entries_to_project: Assign reported hours to the project - text_reassign_time_entries: 'Reassign reported hours to this issue:' - text_user_wrote: "%{value} wrote:" - text_enumeration_destroy_question: "%{count} objects are assigned to this value." - text_enumeration_category_reassign_to: 'Reassign them to this value:' - text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." - text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." - text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.' - text_custom_field_possible_values_info: 'One line for each value' - text_wiki_page_destroy_question: "This page has %{descendants} child page(s) and descendant(s). What do you want to do?" - text_wiki_page_nullify_children: "Keep child pages as root pages" - text_wiki_page_destroy_children: "Delete child pages and all their descendants" - text_wiki_page_reassign_children: "Reassign child pages to this parent page" - text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?" - - default_role_manager: Manager - default_role_developer: Developer - default_role_reporter: Reporter - default_tracker_bug: Bug - default_tracker_feature: Feature - default_tracker_support: Support - default_issue_status_new: New - default_issue_status_in_progress: In Progress - default_issue_status_resolved: Resolved - default_issue_status_feedback: Feedback - default_issue_status_closed: Closed - default_issue_status_rejected: Rejected - default_doc_category_user: User documentation - default_doc_category_tech: Technical documentation - default_priority_low: Low - default_priority_normal: Normal - default_priority_high: High - default_priority_urgent: Urgent - default_priority_immediate: Immediate - default_activity_design: Design - default_activity_development: Development - - enumeration_issue_priorities: Issue priorities - enumeration_doc_categories: Document categories - enumeration_activities: Activities (time tracking) - enumeration_system_activity: System Activity - - notice_unable_delete_time_entry: Unable to delete time log entry. - error_can_not_delete_custom_field: Unable to delete custom field - permission_manage_subtasks: Manage subtasks - label_profile: Profile - error_unable_to_connect: Unable to connect (%{value}) - label_overall_spent_time: Overall spent time - error_can_not_remove_role: This role is in use and can not be deleted. - field_principal: Principal - field_parent_issue: Parent task - label_my_page_block: My page block - text_zoom_out: Zoom out - text_zoom_in: Zoom in - error_unable_delete_issue_status: Unable to delete issue status - label_subtask_plural: Subtasks - error_can_not_delete_tracker: This tracker contains issues and can't be deleted. - notice_failed_to_save_members: "Failed to save member(s): %{errors}." - label_project_copy_notifications: Send email notifications during the project copy - field_time_entries: Log time - project_module_gantt: Gantt - project_module_calendar: Calendar - field_member_of_group: Member of Group - field_assigned_to_role: Member of Role - button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}" - text_are_you_sure_with_children: Delete issue and all child issues? - field_text: Text field - label_user_mail_option_only_owner: Only for things I am the owner of - setting_default_notification_option: Default notification option - label_user_mail_option_only_my_events: Only for things I watch or I'm involved in - label_user_mail_option_only_assigned: Only for things I am assigned to - notice_not_authorized_archived_project: The project you're trying to access has been archived. - label_principal_search: "Search for user or group:" - label_user_search: "Search for user:" - field_visible: Visible - setting_emails_header: Emails header - setting_commit_logtime_activity_id: Activity for logged time - text_time_logged_by_changeset: Applied in changeset %{value}. - setting_commit_logtime_enabled: Enable time logging - notice_gantt_chart_truncated: The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max}) - setting_gantt_items_limit: Maximum number of items displayed on the gantt chart +en-GB: + direction: ltr + date: + formats: + # Use the strftime parameters for formats. + # When no format has been given, it uses default. + # You can provide other formats here if you like! + default: "%d/%m/%Y" + short: "%d %b" + long: "%d %B, %Y" + + day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] + abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat] + + # Don't forget the nil at the beginning; there's no such thing as a 0th month + month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December] + abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec] + # Used in date_select and datime_select. + order: [ :year, :month, :day ] + + time: + formats: + default: "%d/%m/%Y %I:%M %p" + time: "%I:%M %p" + short: "%d %b %H:%M" + long: "%d %B, %Y %H:%M" + am: "am" + pm: "pm" + + datetime: + distance_in_words: + half_a_minute: "half a minute" + less_than_x_seconds: + one: "less than 1 second" + other: "less than %{count} seconds" + x_seconds: + one: "1 second" + other: "%{count} seconds" + less_than_x_minutes: + one: "less than a minute" + other: "less than %{count} minutes" + x_minutes: + one: "1 minute" + other: "%{count} minutes" + about_x_hours: + one: "about 1 hour" + other: "about %{count} hours" + x_days: + one: "1 day" + other: "%{count} days" + about_x_months: + one: "about 1 month" + other: "about %{count} months" + x_months: + one: "1 month" + other: "%{count} months" + about_x_years: + one: "about 1 year" + other: "about %{count} years" + over_x_years: + one: "over 1 year" + other: "over %{count} years" + almost_x_years: + one: "almost 1 year" + other: "almost %{count} years" + + number: + format: + separator: "." + delimiter: " " + precision: 3 + + currency: + format: + format: "%u%n" + unit: "£" + human: + format: + delimiter: "" + precision: 1 + storage_units: + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "kB" + mb: "MB" + gb: "GB" + tb: "TB" + + +# Used in array.to_sentence. + support: + array: + sentence_connector: "and" + skip_last_comma: false + + activerecord: + errors: + template: + header: + one: "1 error prohibited this %{model} from being saved" + other: "%{count} errors prohibited this %{model} from being saved" + messages: + inclusion: "is not included in the list" + exclusion: "is reserved" + invalid: "is invalid" + confirmation: "doesn't match confirmation" + accepted: "must be accepted" + empty: "can't be empty" + blank: "can't be blank" + too_long: "is too long (maximum is %{count} characters)" + too_short: "is too short (minimum is %{count} characters)" + wrong_length: "is the wrong length (should be %{count} characters)" + taken: "has already been taken" + not_a_number: "is not a number" + not_a_date: "is not a valid date" + greater_than: "must be greater than %{count}" + greater_than_or_equal_to: "must be greater than or equal to %{count}" + equal_to: "must be equal to %{count}" + less_than: "must be less than %{count}" + less_than_or_equal_to: "must be less than or equal to %{count}" + odd: "must be odd" + even: "must be even" + greater_than_start_date: "must be greater than start date" + not_same_project: "doesn't belong to the same project" + circular_dependency: "This relation would create a circular dependency" + cant_link_an_issue_with_a_descendant: "An issue can not be linked to one of its subtasks" + + actionview_instancetag_blank_option: Please select + + general_text_No: 'No' + general_text_Yes: 'Yes' + general_text_no: 'no' + general_text_yes: 'yes' + general_lang_name: 'English (British)' + general_csv_separator: ',' + general_csv_decimal_separator: '.' + general_csv_encoding: ISO-8859-1 + general_pdf_encoding: ISO-8859-1 + general_first_day_of_week: '1' + + notice_account_updated: Account was successfully updated. + notice_account_invalid_creditentials: Invalid user or password + notice_account_password_updated: Password was successfully updated. + notice_account_wrong_password: Wrong password + notice_account_register_done: Account was successfully created. To activate your account, click on the link that was emailed to you. + notice_account_unknown_email: Unknown user. + notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password. + notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you. + notice_account_activated: Your account has been activated. You can now log in. + notice_successful_create: Successful creation. + notice_successful_update: Successful update. + notice_successful_delete: Successful deletion. + notice_successful_connection: Successful connection. + notice_file_not_found: The page you were trying to access doesn't exist or has been removed. + notice_locking_conflict: Data has been updated by another user. + notice_not_authorized: You are not authorised to access this page. + notice_email_sent: "An email was sent to %{value}" + notice_email_error: "An error occurred while sending mail (%{value})" + notice_feeds_access_key_reseted: Your RSS access key was reset. + notice_api_access_key_reseted: Your API access key was reset. + notice_failed_to_save_issues: "Failed to save %{count} issue(s) on %{total} selected: %{ids}." + notice_no_issue_selected: "No issue is selected! Please, check the issues you want to edit." + notice_account_pending: "Your account was created and is now pending administrator approval." + notice_default_data_loaded: Default configuration successfully loaded. + notice_unable_delete_version: Unable to delete version. + notice_issue_done_ratios_updated: Issue done ratios updated. + + error_can_t_load_default_data: "Default configuration could not be loaded: %{value}" + error_scm_not_found: "The entry or revision was not found in the repository." + error_scm_command_failed: "An error occurred when trying to access the repository: %{value}" + error_scm_annotate: "The entry does not exist or can not be annotated." + error_issue_not_found_in_project: 'The issue was not found or does not belong to this project' + error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.' + error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").' + error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version can not be reopened' + error_can_not_archive_project: This project can not be archived + error_issue_done_ratios_not_updated: "Issue done ratios not updated." + error_workflow_copy_source: 'Please select a source tracker or role' + error_workflow_copy_target: 'Please select target tracker(s) and role(s)' + + warning_attachments_not_saved: "%{count} file(s) could not be saved." + + mail_subject_lost_password: "Your %{value} password" + mail_body_lost_password: 'To change your password, click on the following link:' + mail_subject_register: "Your %{value} account activation" + mail_body_register: 'To activate your account, click on the following link:' + mail_body_account_information_external: "You can use your %{value} account to log in." + mail_body_account_information: Your account information + mail_subject_account_activation_request: "%{value} account activation request" + mail_body_account_activation_request: "A new user (%{value}) has registered. The account is pending your approval:" + mail_subject_reminder: "%{count} issue(s) due in the next %{days} days" + mail_body_reminder: "%{count} issue(s) that are assigned to you are due in the next %{days} days:" + mail_subject_wiki_content_added: "'%{id}' wiki page has been added" + mail_body_wiki_content_added: "The '%{id}' wiki page has been added by %{author}." + mail_subject_wiki_content_updated: "'%{id}' wiki page has been updated" + mail_body_wiki_content_updated: "The '%{id}' wiki page has been updated by %{author}." + + gui_validation_error: 1 error + gui_validation_error_plural: "%{count} errors" + + field_ssamr_user_detail: + description: User Description + field_name: Name + field_description: Description + field_summary: Summary + field_is_required: Required + field_firstname: First name + field_lastname: Last name + field_mail: Email + field_filename: File + field_filesize: Size + field_downloads: Downloads + field_author: Author + field_created_on: Created + field_updated_on: Updated + field_field_format: Format + field_is_for_all: For all projects + field_possible_values: Possible values + field_regexp: Regular expression + field_min_length: Minimum length + field_max_length: Maximum length + field_value: Value + field_category: Category + field_title: Title + field_project: Project + field_issue: Issue + field_status: Status + field_notes: Notes + field_is_closed: Issue closed + field_is_default: Default value + field_tracker: Tracker + field_subject: Subject + field_due_date: Due date + field_assigned_to: Assignee + field_priority: Priority + field_fixed_version: Target version + field_user: User + field_role: Role + field_homepage: Homepage + field_is_public: Public + field_parent: Subproject of + field_is_in_roadmap: Issues displayed in roadmap + field_login: Login + field_mail_notification: Email notifications + field_admin: Administrator + field_last_login_on: Last connection + field_language: Language + field_effective_date: Date + field_password: Password + field_new_password: New password + field_password_confirmation: Confirmation + field_version: Version + field_type: Type + field_host: Host + field_port: Port + field_account: Account + field_base_dn: Base DN + field_attr_login: Login attribute + field_attr_firstname: Firstname attribute + field_attr_lastname: Lastname attribute + field_attr_mail: Email attribute + field_onthefly: On-the-fly user creation + field_start_date: Start date + field_done_ratio: % Done + field_auth_source: Authentication mode + field_hide_mail: Hide my email address + field_comments: Comment + field_url: URL + field_start_page: Start page + field_subproject: Subproject + field_hours: Hours + field_activity: Activity + field_spent_on: Date + field_identifier: Identifier + field_is_filter: Used as a filter + field_issue_to: Related issue + field_delay: Delay + field_assignable: Issues can be assigned to this role + field_redirect_existing_links: Redirect existing links + field_estimated_hours: Estimated time + field_column_names: Columns + field_time_zone: Time zone + field_searchable: Searchable + field_default_value: Default value + field_comments_sorting: Display comments + field_parent_title: Parent page + field_editable: Editable + field_watcher: Watcher + field_identity_url: OpenID URL + field_content: Content + field_group_by: Group results by + field_sharing: Sharing + + setting_app_title: Application title + setting_app_subtitle: Application subtitle + setting_welcome_text: Welcome text + setting_tipoftheday_text: Tip of the Day + setting_notifications_text: Notifications + setting_default_language: Default language + setting_login_required: Authentication required + setting_self_registration: Self-registration + setting_attachment_max_size: Attachment max. size + setting_issues_export_limit: Issues export limit + setting_mail_from: Emission email address + setting_bcc_recipients: Blind carbon copy recipients (bcc) + setting_plain_text_mail: Plain text mail (no HTML) + setting_host_name: Host name and path + setting_text_formatting: Text formatting + setting_wiki_compression: Wiki history compression + setting_feeds_limit: Feed content limit + setting_default_projects_public: New projects are public by default + setting_autofetch_changesets: Autofetch commits + setting_sys_api_enabled: Enable WS for repository management + setting_commit_ref_keywords: Referencing keywords + setting_commit_fix_keywords: Fixing keywords + setting_autologin: Autologin + setting_date_format: Date format + setting_time_format: Time format + setting_cross_project_issue_relations: Allow cross-project issue relations + setting_issue_list_default_columns: Default columns displayed on the issue list + setting_repositories_encodings: Repositories encodings + setting_commit_logs_encoding: Commit messages encoding + setting_emails_footer: Emails footer + setting_protocol: Protocol + setting_per_page_options: Objects per page options + setting_user_format: Users display format + setting_activity_days_default: Days displayed on project activity + setting_display_subprojects_issues: Display subprojects issues on main projects by default + setting_enabled_scm: Enabled SCM + setting_mail_handler_body_delimiters: "Truncate emails after one of these lines" + setting_mail_handler_api_enabled: Enable WS for incoming emails + setting_mail_handler_api_key: API key + setting_sequential_project_identifiers: Generate sequential project identifiers + setting_gravatar_enabled: Use Gravatar user icons + setting_gravatar_default: Default Gravatar image + setting_diff_max_lines_displayed: Max number of diff lines displayed + setting_file_max_size_displayed: Max size of text files displayed inline + setting_repository_log_display_limit: Maximum number of revisions displayed on file log + setting_openid: Allow OpenID login and registration + setting_password_min_length: Minimum password length + setting_new_project_user_role_id: Role given to a non-admin user who creates a project + setting_default_projects_modules: Default enabled modules for new projects + setting_issue_done_ratio: Calculate the issue done ratio with + setting_issue_done_ratio_issue_field: Use the issue field + setting_issue_done_ratio_issue_status: Use the issue status + setting_start_of_week: Start calendars on + setting_rest_api_enabled: Enable REST web service + setting_cache_formatted_text: Cache formatted text + + permission_add_project: Create project + permission_add_subprojects: Create subprojects + permission_edit_project: Edit project + permission_select_project_modules: Select project modules + permission_manage_members: Manage members + permission_manage_project_activities: Manage project activities + permission_manage_versions: Manage versions + permission_manage_categories: Manage issue categories + permission_view_issues: View Issues + permission_add_issues: Add issues + permission_edit_issues: Edit issues + permission_manage_issue_relations: Manage issue relations + permission_add_issue_notes: Add notes + permission_edit_issue_notes: Edit notes + permission_edit_own_issue_notes: Edit own notes + permission_move_issues: Move issues + permission_delete_issues: Delete issues + permission_manage_public_queries: Manage public queries + permission_save_queries: Save queries + permission_view_gantt: View gantt chart + permission_view_calendar: View calendar + permission_view_issue_watchers: View watchers list + permission_add_issue_watchers: Add watchers + permission_delete_issue_watchers: Delete watchers + permission_log_time: Log spent time + permission_view_time_entries: View spent time + permission_edit_time_entries: Edit time logs + permission_edit_own_time_entries: Edit own time logs + permission_manage_news: Manage news + permission_comment_news: Comment news + permission_manage_documents: Manage documents + permission_view_documents: View documents + permission_manage_files: Manage files + permission_view_files: View files + permission_manage_wiki: Manage wiki + permission_rename_wiki_pages: Rename wiki pages + permission_delete_wiki_pages: Delete wiki pages + permission_view_wiki_pages: View wiki + permission_view_wiki_edits: View wiki history + permission_edit_wiki_pages: Edit wiki pages + permission_delete_wiki_pages_attachments: Delete attachments + permission_protect_wiki_pages: Protect wiki pages + permission_manage_repository: Manage repository + permission_browse_repository: Browse repository + permission_view_changesets: View changesets + permission_commit_access: Commit access + permission_manage_boards: Manage boards + permission_view_messages: View messages + permission_add_messages: Post messages + permission_edit_messages: Edit messages + permission_edit_own_messages: Edit own messages + permission_delete_messages: Delete messages + permission_delete_own_messages: Delete own messages + permission_export_wiki_pages: Export wiki pages + + project_module_issue_tracking: Issue tracking + project_module_time_tracking: Time tracking + project_module_news: News + project_module_documents: Documents + project_module_files: Files + project_module_wiki: Wiki + project_module_repository: Repository + project_module_boards: Boards + + label_tipoftheday: Tip of the day + label_notifications: Important Message + label_ssamr_description: Research description + label_ssamr_details: Other Details + + label_user: User + label_user_plural: Users + label_user_new: New user + label_user_anonymous: Anonymous + label_project: Project + label_project_new: New project + label_project_plural: Projects + label_my_project_plural: My Projects + label_other_project_plural: "Everyone Else's Projects" + label_x_projects: + zero: no projects + one: 1 project + other: "%{count} projects" + label_project_all: All Projects + label_project_latest: Latest projects + label_issue: Issue + label_issue_new: New issue + label_issue_plural: Issues + label_issue_view_all: View all issues + label_issues_by: "Issues by %{value}" + label_issue_added: Issue added + label_issue_updated: Issue updated + label_document: Document + label_document_new: New document + label_document_plural: Documents + label_document_added: Document added + label_role: Role + label_role_plural: Roles + label_role_new: New role + label_role_and_permissions: Roles and permissions + label_member: Member + label_member_new: New member + label_member_plural: Members + label_tracker: Tracker + label_tracker_plural: Trackers + label_tracker_new: New tracker + label_workflow: Workflow + label_issue_status: Issue status + label_issue_status_plural: Issue statuses + label_issue_status_new: New status + label_issue_category: Issue category + label_issue_category_plural: Issue categories + label_issue_category_new: New category + label_custom_field: Custom field + label_custom_field_plural: Custom fields + label_custom_field_new: New custom field + label_enumerations: Enumerations + label_enumeration_new: New value + label_information: Information + label_information_plural: Information + label_please_login: Please log in + label_register: Register + label_login_with_open_id_option: or login with OpenID + label_password_lost: Lost password + label_home: Home + label_home_heading: Welcome! + label_my_page: My page + label_my_account: My account + label_my_projects: My projects + label_administration: Administration + label_login: Sign in + label_logout: Sign out + label_help: Help + label_reported_issues: Reported issues + label_assigned_to_me_issues: Issues assigned to me + label_last_login: Last connection + label_registered_on: Registered on + label_activity: Activity + label_overall_activity: Overall activity + label_user_activity: "%{value}'s activity" + label_new: New + label_logged_as: Logged in as + label_environment: Environment + label_authentication: Authentication + label_auth_source: Authentication mode + label_auth_source_new: New authentication mode + label_auth_source_plural: Authentication modes + label_subproject_plural: Subprojects + label_subproject_new: New subproject + label_and_its_subprojects: "%{value} and its subprojects" + label_min_max_length: Min - Max length + label_list: List + label_date: Date + label_integer: Integer + label_float: Float + label_boolean: Boolean + label_string: Text + label_text: Long text + label_attribute: Attribute + label_attribute_plural: Attributes + label_download: "%{count} Download" + label_download_plural: "%{count} Downloads" + label_no_data: No data to display + label_change_status: Change status + label_history: History + label_attachment: File + label_attachment_new: New file + label_attachment_delete: Delete file + label_attachment_plural: Files + label_file_added: File added + label_report: Report + label_report_plural: Reports + label_news: News + label_news_new: Add news + label_news_plural: News + label_news_latest: Latest news + label_news_view_all: View all news + label_news_added: News added + label_settings: Settings + label_overview: Overview + label_version: Version + label_version_new: New version + label_version_plural: Versions + label_close_versions: Close completed versions + label_confirmation: Confirmation + label_export_to: 'Also available in:' + label_read: Read... + label_public_projects: Public projects + label_open_issues: open + label_open_issues_plural: open + label_closed_issues: closed + label_closed_issues_plural: closed + label_x_open_issues_abbr_on_total: + zero: 0 open / %{total} + one: 1 open / %{total} + other: "%{count} open / %{total}" + label_x_open_issues_abbr: + zero: 0 open + one: 1 open + other: "%{count} open" + label_x_closed_issues_abbr: + zero: 0 closed + one: 1 closed + other: "%{count} closed" + label_total: Total + label_permissions: Permissions + label_current_status: Current status + label_new_statuses_allowed: New statuses allowed + label_all: all + label_none: none + label_nobody: nobody + label_next: Next + label_previous: Previous + label_used_by: Used by + label_details: Details + label_add_note: Add a note + label_per_page: Per page + label_calendar: Calendar + label_months_from: months from + label_gantt: Gantt + label_internal: Internal + label_last_changes: "last %{count} changes" + label_change_view_all: View all changes + label_personalize_page: Personalise this page + label_comment: Comment + label_comment_plural: Comments + label_x_comments: + zero: no comments + one: 1 comment + other: "%{count} comments" + label_comment_add: Add a comment + label_comment_added: Comment added + label_comment_delete: Delete comments + label_query: Custom query + label_query_plural: Custom queries + label_query_new: New query + label_filter_add: Add filter + label_filter_plural: Filters + label_equals: is + label_not_equals: is not + label_in_less_than: in less than + label_in_more_than: in more than + label_greater_or_equal: '>=' + label_less_or_equal: '<=' + label_in: in + label_today: today + label_all_time: all time + label_yesterday: yesterday + label_this_week: this week + label_last_week: last week + label_last_n_days: "last %{count} days" + label_this_month: this month + label_last_month: last month + label_this_year: this year + label_date_range: Date range + label_less_than_ago: less than days ago + label_more_than_ago: more than days ago + label_ago: days ago + label_contains: contains + label_not_contains: doesn't contain + label_day_plural: days + label_repository: Repository + label_repository_plural: Repositories + label_browse: Browse + label_modification: "%{count} change" + label_modification_plural: "%{count} changes" + label_branch: Branch + label_tag: Tag + label_revision: Revision + label_revision_plural: Revisions + label_revision_id: "Revision %{value}" + label_associated_revisions: Associated revisions + label_added: added + label_modified: modified + label_copied: copied + label_renamed: renamed + label_deleted: deleted + label_latest_revision: Latest revision + label_latest_revision_plural: Latest revisions + label_view_revisions: View revisions + label_view_all_revisions: View all revisions + label_max_size: Maximum size + label_sort_highest: Move to top + label_sort_higher: Move up + label_sort_lower: Move down + label_sort_lowest: Move to bottom + label_roadmap: Roadmap + label_roadmap_due_in: "Due in %{value}" + label_roadmap_overdue: "%{value} late" + label_roadmap_no_issues: No issues for this version + label_search: Search + label_result_plural: Results + label_all_words: All words + label_wiki: Wiki + label_wiki_edit: Wiki edit + label_wiki_edit_plural: Wiki edits + label_wiki_page: Wiki page + label_wiki_page_plural: Wiki pages + label_index_by_title: Index by title + label_index_by_date: Index by date + label_current_version: Current version + label_preview: Preview + label_feed_plural: Feeds + label_changes_details: Details of all changes + label_issue_tracking: Issue tracking + label_spent_time: Spent time + label_f_hour: "%{value} hour" + label_f_hour_plural: "%{value} hours" + label_time_tracking: Time tracking + label_change_plural: Changes + label_statistics: Statistics + label_commits_per_month: Commits per month + label_commits_per_author: Commits per author + label_view_diff: View differences + label_diff_inline: inline + label_diff_side_by_side: side by side + label_options: Options + label_copy_workflow_from: Copy workflow from + label_permissions_report: Permissions report + label_watched_issues: Watched issues + label_related_issues: Related issues + label_applied_status: Applied status + label_loading: Loading... + label_relation_new: New relation + label_relation_delete: Delete relation + label_relates_to: related to + label_duplicates: duplicates + label_duplicated_by: duplicated by + label_blocks: blocks + label_blocked_by: blocked by + label_precedes: precedes + label_follows: follows + label_end_to_start: end to start + label_end_to_end: end to end + label_start_to_start: start to start + label_start_to_end: start to end + label_stay_logged_in: Stay logged in + label_disabled: disabled + label_show_completed_versions: Show completed versions + label_me: me + label_board: Forum + label_board_new: New forum + label_board_plural: Forums + label_board_locked: Locked + label_board_sticky: Sticky + label_topic_plural: Topics + label_message_plural: Messages + label_message_last: Last message + label_message_new: New message + label_message_posted: Message added + label_reply_plural: Replies + label_send_information: Send account information to the user + label_year: Year + label_month: Month + label_week: Week + label_date_from: From + label_date_to: To + label_language_based: "Based on user's language" + label_sort_by: "Sort by %{value}" + label_send_test_email: Send a test email + label_feeds_access_key: RSS access key + label_missing_feeds_access_key: Missing a RSS access key + label_feeds_access_key_created_on: "RSS access key created %{value} ago" + label_module_plural: Modules + label_added_time_by: "Added by %{author} %{age} ago" + label_updated_time_by: "Updated by %{author} %{age} ago" + label_updated_time: "Updated %{value} ago" + label_jump_to_a_project: Jump to a project... + label_file_plural: Files + label_changeset_plural: Changesets + label_default_columns: Default columns + label_no_change_option: (No change) + label_bulk_edit_selected_issues: Bulk edit selected issues + label_theme: Theme + label_default: Default + label_search_titles_only: Search titles only + label_user_mail_option_all: "For any event on all my projects" + label_user_mail_option_selected: "For any event on the selected projects only..." + label_user_mail_option_none: "No events" + label_user_mail_no_self_notified: "I don't want to be notified of changes that I make myself" + label_registration_activation_by_email: account activation by email + label_registration_manual_activation: manual account activation + label_registration_automatic_activation: automatic account activation + label_display_per_page: "Per page: %{value}" + label_age: Age + label_change_properties: Change properties + label_general: General + label_more: More + label_scm: SCM + label_plugins: Plugins + label_ldap_authentication: LDAP authentication + label_downloads_abbr: D/L + label_optional_description: Optional description + label_add_another_file: Add another file + label_preferences: Preferences + label_chronological_order: In chronological order + label_reverse_chronological_order: In reverse chronological order + label_planning: Planning + label_incoming_emails: Incoming emails + label_generate_key: Generate a key + label_issue_watchers: Watchers + label_example: Example + label_display: Display + label_sort: Sort + label_ascending: Ascending + label_descending: Descending + label_date_from_to: From %{start} to %{end} + label_wiki_content_added: Wiki page added + label_wiki_content_updated: Wiki page updated + label_group: Group + label_group_plural: Groups + label_group_new: New group + label_time_entry_plural: Spent time + label_version_sharing_none: Not shared + label_version_sharing_descendants: With subprojects + label_version_sharing_hierarchy: With project hierarchy + label_version_sharing_tree: With project tree + label_version_sharing_system: With all projects + label_update_issue_done_ratios: Update issue done ratios + label_copy_source: Source + label_copy_target: Target + label_copy_same_as_target: Same as target + label_display_used_statuses_only: Only display statuses that are used by this tracker + label_api_access_key: API access key + label_missing_api_access_key: Missing an API access key + label_api_access_key_created_on: "API access key created %{value} ago" + + button_login: Login + button_submit: Submit + button_save: Save + button_check_all: Check all + button_uncheck_all: Uncheck all + button_delete: Delete + button_create: Create + button_create_and_continue: Create and continue + button_test: Test + button_edit: Edit + button_add: Add + button_change: Change + button_apply: Apply + button_clear: Clear + button_lock: Lock + button_unlock: Unlock + button_download: Download + button_list: List + button_view: View + button_move: Move + button_move_and_follow: Move and follow + button_back: Back + button_cancel: Cancel + button_activate: Activate + button_sort: Sort + button_log_time: Log time + button_rollback: Rollback to this version + button_watch: Watch + button_unwatch: Unwatch + button_reply: Reply + button_archive: Archive + button_unarchive: Unarchive + button_reset: Reset + button_rename: Rename + button_change_password: Change password + button_copy: Copy + button_copy_and_follow: Copy and follow + button_annotate: Annotate + button_update: Update + button_configure: Configure + button_quote: Quote + button_duplicate: Duplicate + button_show: Show + + status_active: active + status_registered: registered + status_locked: locked + + version_status_open: open + version_status_locked: locked + version_status_closed: closed + + field_active: Active + + text_select_mail_notifications: Select actions for which email notifications should be sent. + text_regexp_info: eg. ^[A-Z0-9]+$ + text_min_max_length_info: 0 means no restriction + text_project_destroy_confirmation: Are you sure you want to delete this project and related data? + text_subprojects_destroy_warning: "Its subproject(s): %{value} will be also deleted." + text_workflow_edit: Select a role and a tracker to edit the workflow + text_are_you_sure: Are you sure? + text_journal_changed: "%{label} changed from %{old} to %{new}" + text_journal_set_to: "%{label} set to %{value}" + text_journal_deleted: "%{label} deleted (%{old})" + text_journal_added: "%{label} %{value} added" + text_tip_issue_begin_day: task beginning this day + text_tip_issue_end_day: task ending this day + text_tip_issue_begin_end_day: task beginning and ending this day + text_project_identifier_info: 'Only lower case letters (a-z), numbers and dashes are allowed.<br /> This will be used in all project-related URLs, and as the repository name. Once saved, the identifier <b>can not</b> be changed.' + text_project_homepage_info: 'Link to an external project page.' + text_project_name_info: "This will be the name of your project throughout this site.<br /> You can change your project's name at any time, in the project's settings." + text_project_visibility_info: "If your project is not public, it will only be visible to users that you have added as project members." + text_user_ssamr_description_info: 'Please describe your current research or development interests, within the fields of audio and music.<br/>This information is publicly visible in your profile and you can edit it at any time.<br/>It may also be used to establish eligibility for your initial registration.' + text_issue_parent_issue_info: 'If this is a subtask, please insert its parent task number or write the main task name.' + text_tracker_no_workflow: No workflow defined for this tracker + text_unallowed_characters: Unallowed characters + text_comma_separated: Multiple values allowed (comma separated). + text_line_separated: Multiple values allowed (one line for each value). + text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages + text_issue_added: "Issue %{id} has been reported by %{author}." + text_issue_updated: "Issue %{id} has been updated by %{author}." + text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and all its content? + text_issue_category_destroy_question: "Some issues (%{count}) are assigned to this category. What do you want to do?" + text_issue_category_destroy_assignments: Remove category assignments + text_issue_category_reassign_to: Reassign issues to this category + text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)." + text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded." + text_load_default_configuration: Load the default configuration + text_status_changed_by_changeset: "Applied in changeset %{value}." + text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?' + text_select_project_modules: 'Select modules to enable for this project:' + text_default_administrator_account_changed: Default administrator account changed + text_file_repository_writable: Attachments directory writable + text_plugin_assets_writable: Plugin assets directory writable + text_rmagick_available: RMagick available (optional) + text_destroy_time_entries_question: "%{hours} hours were reported on the issues you are about to delete. What do you want to do?" + text_destroy_time_entries: Delete reported hours + text_assign_time_entries_to_project: Assign reported hours to the project + text_reassign_time_entries: 'Reassign reported hours to this issue:' + text_user_wrote: "%{value} wrote:" + text_enumeration_destroy_question: "%{count} objects are assigned to this value." + text_enumeration_category_reassign_to: 'Reassign them to this value:' + text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." + text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." + text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.' + text_custom_field_possible_values_info: 'One line for each value' + text_wiki_page_destroy_question: "This page has %{descendants} child page(s) and descendant(s). What do you want to do?" + text_wiki_page_nullify_children: "Keep child pages as root pages" + text_wiki_page_destroy_children: "Delete child pages and all their descendants" + text_wiki_page_reassign_children: "Reassign child pages to this parent page" + text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?" + + default_role_manager: Manager + default_role_developer: Developer + default_role_reporter: Reporter + default_tracker_bug: Bug + default_tracker_feature: Feature + default_tracker_support: Support + default_issue_status_new: New + default_issue_status_in_progress: In Progress + default_issue_status_resolved: Resolved + default_issue_status_feedback: Feedback + default_issue_status_closed: Closed + default_issue_status_rejected: Rejected + default_doc_category_user: User documentation + default_doc_category_tech: Technical documentation + default_priority_low: Low + default_priority_normal: Normal + default_priority_high: High + default_priority_urgent: Urgent + default_priority_immediate: Immediate + default_activity_design: Design + default_activity_development: Development + + enumeration_issue_priorities: Issue priorities + enumeration_doc_categories: Document categories + enumeration_activities: Activities (time tracking) + enumeration_system_activity: System Activity + + notice_unable_delete_time_entry: Unable to delete time log entry. + error_can_not_delete_custom_field: Unable to delete custom field + permission_manage_subtasks: Manage subtasks + label_profile: Profile + error_unable_to_connect: Unable to connect (%{value}) + label_overall_spent_time: Overall spent time + error_can_not_remove_role: This role is in use and can not be deleted. + field_principal: Principal + field_parent_issue: Parent task + label_my_page_block: My page block + text_zoom_out: Zoom out + text_zoom_in: Zoom in + error_unable_delete_issue_status: Unable to delete issue status + label_subtask_plural: Subtasks + error_can_not_delete_tracker: This tracker contains issues and can't be deleted. + notice_failed_to_save_members: "Failed to save member(s): %{errors}." + label_project_copy_notifications: Send email notifications during the project copy + field_time_entries: Log time + project_module_gantt: Gantt + project_module_calendar: Calendar + field_member_of_group: Member of Group + field_assigned_to_role: Member of Role + button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}" + text_are_you_sure_with_children: Delete issue and all child issues? + field_text: Text field + label_user_mail_option_only_owner: Only for things I am the owner of + setting_default_notification_option: Default notification option + label_user_mail_option_only_my_events: Only for things I watch or I'm involved in + label_user_mail_option_only_assigned: Only for things I am assigned to + notice_not_authorized_archived_project: The project you're trying to access has been archived. + label_principal_search: "Search for user or group:" + label_user_search: "Search for user:" + field_visible: Visible + setting_emails_header: Emails header + setting_commit_logtime_activity_id: Activity for logged time + text_time_logged_by_changeset: Applied in changeset %{value}. + setting_commit_logtime_enabled: Enable time logging + notice_gantt_chart_truncated: The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max}) + setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
--- a/config/locales/en.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/en.yml Thu Jan 13 13:21:03 2011 +0000 @@ -205,13 +205,15 @@ gui_validation_error: 1 error gui_validation_error_plural: "%{count} errors" - + + field_ssamr_user_detail: + description: User Description field_name: Name field_description: Description field_summary: Summary field_is_required: Required - field_firstname: Firstname - field_lastname: Lastname + field_firstname: First name + field_lastname: Last name field_mail: Email field_filename: File field_filesize: Size @@ -304,6 +306,9 @@ field_text: Text field field_visible: Visible + setting_tipoftheday_text: Tip of the Day + setting_notifications_text: Notifications + label_ssamr_description: Research description setting_app_title: Application title setting_app_subtitle: Application subtitle setting_welcome_text: Welcome text @@ -430,6 +435,8 @@ project_module_calendar: Calendar project_module_gantt: Gantt + label_tipoftheday: Tip of the day + label_ssamr_details: Other Details label_user: User label_user_plural: Users label_user_new: New user @@ -437,6 +444,8 @@ label_project: Project label_project_new: New project label_project_plural: Projects + label_my_project_plural: My Projects + label_other_project_plural: "Everyone Else's Projects" label_x_projects: zero: no projects one: 1 project @@ -483,6 +492,7 @@ label_login_with_open_id_option: or login with OpenID label_password_lost: Lost password label_home: Home + label_home_heading: Welcome! label_my_page: My page label_my_account: My account label_my_projects: My projects @@ -864,10 +874,12 @@ text_tip_issue_begin_day: issue beginning this day text_tip_issue_end_day: issue ending this day text_tip_issue_begin_end_day: issue beginning and ending this day - text_project_identifier_info: 'Only lower case letters (a-z), numbers and dashes are allowed.<br />Once saved, the identifier can not be changed.' - text_caracters_maximum: "%{count} characters maximum." - text_caracters_minimum: "Must be at least %{count} characters long." - text_length_between: "Length between %{min} and %{max} characters." + text_project_identifier_info: 'Only lower case letters (a-z), numbers and dashes are allowed.<br /> This will be used in all project-related URLs, and as the repository name. Once saved, the identifier <b>can not</b> be changed.' + text_project_name_info: "This will be the name of your project throughout this site.<br /> You can change your project's name at any time, in the project's settings." + text_project_visibility_info: "If your project is not public, it will only be visible to users that you have added as project members." + text_project_homepage_info: 'Link to an external project page.' + text_user_ssamr_description_info: 'Please describe your current research or development interests, within the fields of audio and music.<br/>This information is publicly visible in your profile and you can edit it at any time.<br/>It may also be used to establish eligibility for your initial registration.' + text_issue_parent_issue_info: 'If this is a subtask, please insert its parent task number or write the main task name.' text_tracker_no_workflow: No workflow defined for this tracker text_unallowed_characters: Unallowed characters text_comma_separated: Multiple values allowed (comma separated).
--- a/config/locales/es.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/es.yml Thu Jan 13 13:21:03 2011 +0000 @@ -461,6 +461,7 @@ label_help: Ayuda label_history: Histórico label_home: Inicio + label_home_heading: Inicio label_in: en label_in_less_than: en menos que label_in_more_than: en más que
--- a/config/locales/eu.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/eu.yml Thu Jan 13 13:21:03 2011 +0000 @@ -460,6 +460,7 @@ label_login_with_open_id_option: edo OpenID-rekin saioa hasi label_password_lost: Pasahitza galduta label_home: Hasiera + label_home_heading: Hasiera label_my_page: Nire orria label_my_account: Nire kontua label_my_projects: Nire proiektuak
--- a/config/locales/fi.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/fi.yml Thu Jan 13 13:21:03 2011 +0000 @@ -361,6 +361,7 @@ label_register: Rekisteröidy label_password_lost: Hukattu salasana label_home: Koti + label_home_heading: Koti label_my_page: Omasivu label_my_account: Oma tili label_my_projects: Omat projektit
--- a/config/locales/fr.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/fr.yml Thu Jan 13 13:21:03 2011 +0000 @@ -483,6 +483,7 @@ label_login_with_open_id_option: S'authentifier avec OpenID label_password_lost: Mot de passe perdu label_home: Accueil + label_home_heading: Accueil label_my_page: Ma page label_my_account: Mon compte label_my_projects: Mes projets
--- a/config/locales/gl.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/gl.yml Thu Jan 13 13:21:03 2011 +0000 @@ -438,6 +438,7 @@ label_help: Axuda label_history: Histórico label_home: Inicio + label_home_heading: Inicio label_in: en label_in_less_than: en menos que label_in_more_than: en mais que
--- a/config/locales/he.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/he.yml Thu Jan 13 13:21:03 2011 +0000 @@ -479,6 +479,7 @@ label_login_with_open_id_option: או התחבר באמצעות OpenID label_password_lost: אבדה הסיסמה? label_home: דף הבית + label_home_heading: דף הבית label_my_page: הדף שלי label_my_account: החשבון שלי label_my_projects: הפרויקטים שלי
--- a/config/locales/hr.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/hr.yml Thu Jan 13 13:21:03 2011 +0000 @@ -455,6 +455,7 @@ label_login_with_open_id_option: or login with OpenID label_password_lost: Izgubljena zaporka label_home: Početna stranica + label_home_heading: Početna stranica label_my_page: Moja stranica label_my_account: Moj profil label_my_projects: Moji projekti
--- a/config/locales/hu.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/hu.yml Thu Jan 13 13:21:03 2011 +0000 @@ -377,6 +377,7 @@ label_register: Regisztráljon label_password_lost: Elfelejtett jelszó label_home: Kezdőlap + label_home_heading: Kezdőlap label_my_page: Saját kezdőlapom label_my_account: Fiókom adatai label_my_projects: Saját projektem
--- a/config/locales/id.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/id.yml Thu Jan 13 13:21:03 2011 +0000 @@ -446,6 +446,7 @@ label_login_with_open_id_option: atau login menggunakan OpenID label_password_lost: Lupa password label_home: Halaman depan + label_home_heading: Halaman depan label_my_page: Beranda label_my_account: Akun saya label_my_projects: Proyek saya
--- a/config/locales/it.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/it.yml Thu Jan 13 13:21:03 2011 +0000 @@ -321,6 +321,7 @@ label_register: Registrati label_password_lost: Password dimenticata label_home: Home + label_home_heading: Home label_my_page: Pagina personale label_my_account: Il mio utente label_my_projects: I miei progetti
--- a/config/locales/ja.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/ja.yml Thu Jan 13 13:21:03 2011 +0000 @@ -506,6 +506,7 @@ label_login_with_open_id_option: またはOpenIDでログインする label_password_lost: パスワードの再発行 label_home: ホーム + label_home_heading: ホーム label_my_page: マイページ label_my_account: 個人設定 label_my_projects: マイプロジェクト
--- a/config/locales/ko.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/ko.yml Thu Jan 13 13:21:03 2011 +0000 @@ -485,6 +485,7 @@ label_login_with_open_id_option: 또는 OpenID로 로그인 label_password_lost: 비밀번호 찾기 label_home: 초기화면 + label_home_heading: 초기화면 label_my_page: 내 페이지 label_my_account: 내 계정 label_my_projects: 내 프로젝트
--- a/config/locales/lt.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/lt.yml Thu Jan 13 13:21:03 2011 +0000 @@ -501,6 +501,7 @@ label_register: Užsiregistruoti label_password_lost: Prarastas slaptažodis label_home: Pagrindinis + label_home_heading: Pagrindinis label_my_page: Mano puslapis label_my_account: Mano paskyra label_my_projects: Mano projektai
--- a/config/locales/lv.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/lv.yml Thu Jan 13 13:21:03 2011 +0000 @@ -454,6 +454,7 @@ label_login_with_open_id_option: vai pieslēgties ar OpenID label_password_lost: Nozaudēta parole label_home: Sākums + label_home_heading: Sākums label_my_page: Mana lapa label_my_account: Mans konts label_my_projects: Mani projekti
--- a/config/locales/mk.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/mk.yml Thu Jan 13 13:21:03 2011 +0000 @@ -472,6 +472,7 @@ label_login_with_open_id_option: или најави се со OpenID label_password_lost: Изгубена лозинка label_home: Почетна + label_home_heading: Почетна label_my_page: Мојата страна label_my_account: Мојот профил label_my_projects: Мои проекти
--- a/config/locales/mn.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/mn.yml Thu Jan 13 13:21:03 2011 +0000 @@ -458,6 +458,7 @@ label_login_with_open_id_option: or login with OpenID label_password_lost: Нууц үгээ алдсан label_home: Нүүр + label_home_heading: Нүүр label_my_page: Миний хуудас label_my_account: Миний данс label_my_projects: Миний төслүүд
--- a/config/locales/nl.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/nl.yml Thu Jan 13 13:21:03 2011 +0000 @@ -408,6 +408,7 @@ label_help: Help label_history: Geschiedenis label_home: Home + label_home_heading: Home label_in: in label_in_less_than: in minder dan label_in_more_than: in meer dan
--- a/config/locales/no.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/no.yml Thu Jan 13 13:21:03 2011 +0000 @@ -348,6 +348,7 @@ label_register: Registrer label_password_lost: Mistet passord label_home: Hjem + label_home_heading: Hjem label_my_page: Min side label_my_account: Min konto label_my_projects: Mine prosjekter
--- a/config/locales/pl.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/pl.yml Thu Jan 13 13:21:03 2011 +0000 @@ -435,6 +435,7 @@ label_help: Pomoc label_history: Historia label_home: Główna + label_home_heading: Główna label_in: w label_in_less_than: mniejsze niż label_in_more_than: większe niż
--- a/config/locales/pt-BR.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/pt-BR.yml Thu Jan 13 13:21:03 2011 +0000 @@ -386,6 +386,7 @@ label_register: Cadastre-se label_password_lost: Perdi minha senha label_home: Página inicial + label_home_heading: Página inicial label_my_page: Minha página label_my_account: Minha conta label_my_projects: Meus projetos
--- a/config/locales/pt.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/pt.yml Thu Jan 13 13:21:03 2011 +0000 @@ -371,6 +371,7 @@ label_register: Registar label_password_lost: Perdi a palavra-chave label_home: Página Inicial + label_home_heading: Página Inicial label_my_page: Página Pessoal label_my_account: Minha conta label_my_projects: Meus projectos
--- a/config/locales/ro.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/ro.yml Thu Jan 13 13:21:03 2011 +0000 @@ -418,6 +418,7 @@ label_login_with_open_id_option: sau autentificare cu OpenID label_password_lost: Parolă uitată label_home: Acasă + label_home_heading: Acasă label_my_page: Pagina mea label_my_account: Contul meu label_my_projects: Proiectele mele
--- a/config/locales/ru.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/ru.yml Thu Jan 13 13:21:03 2011 +0000 @@ -516,6 +516,7 @@ label_help: Помощь label_history: История label_home: Домашняя страница + label_home_heading: Домашняя страница label_incoming_emails: Приём сообщений label_index_by_date: История страниц label_index_by_title: Оглавление
--- a/config/locales/sk.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/sk.yml Thu Jan 13 13:21:03 2011 +0000 @@ -351,6 +351,7 @@ label_register: Registrovať label_password_lost: Zabudnuté heslo label_home: Domovská stránka + label_home_heading: Domovská stránka label_my_page: Moja stránka label_my_account: Môj účet label_my_projects: Moje projekty
--- a/config/locales/sl.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/sl.yml Thu Jan 13 13:21:03 2011 +0000 @@ -414,6 +414,7 @@ label_register: Registracija label_password_lost: Izgubljeno geslo label_home: Domov + label_home_heading: Domov label_my_page: Moja stran label_my_account: Moj račun label_my_projects: Moji projekti
--- a/config/locales/sr-YU.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/sr-YU.yml Thu Jan 13 13:21:03 2011 +0000 @@ -469,6 +469,7 @@ label_login_with_open_id_option: ili prijava sa OpenID label_password_lost: Izgubljena lozinka label_home: Početak + label_home_heading: Početak label_my_page: Moja stranica label_my_account: Moj nalog label_my_projects: Moji projekti
--- a/config/locales/sr.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/sr.yml Thu Jan 13 13:21:03 2011 +0000 @@ -469,6 +469,7 @@ label_login_with_open_id_option: или пријава са OpenID label_password_lost: Изгубљена лозинка label_home: Почетак + label_home_heading: Почетак label_my_page: Моја страница label_my_account: Мој налог label_my_projects: Моји пројекти
--- a/config/locales/sv.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/sv.yml Thu Jan 13 13:21:03 2011 +0000 @@ -521,6 +521,7 @@ label_login_with_open_id_option: eller logga in med OpenID label_password_lost: Glömt lösenord label_home: Hem + label_home_heading: Hem label_my_page: Min sida label_my_account: Mitt konto label_my_projects: Mina projekt
--- a/config/locales/th.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/th.yml Thu Jan 13 13:21:03 2011 +0000 @@ -353,6 +353,7 @@ label_register: ลงทะเบียน label_password_lost: ลืมรหัสผ่าน label_home: หน้าแรก + label_home_heading: หน้าแรก label_my_page: หน้าของฉัน label_my_account: บัญชีของฉัน label_my_projects: โครงการของฉัน
--- a/config/locales/tr.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/tr.yml Thu Jan 13 13:21:03 2011 +0000 @@ -376,6 +376,7 @@ label_register: Kayıt label_password_lost: Parolamı unuttum? label_home: Anasayfa + label_home_heading: Anasayfa label_my_page: Kişisel Sayfam label_my_account: Hesabım label_my_projects: Projelerim
--- a/config/locales/uk.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/uk.yml Thu Jan 13 13:21:03 2011 +0000 @@ -328,6 +328,7 @@ label_register: Зареєструватися label_password_lost: Забули пароль label_home: Домашня сторінка + label_home_heading: Домашня сторінка label_my_page: Моя сторінка label_my_account: Мій обліковий запис label_my_projects: Мої проекти
--- a/config/locales/vi.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/vi.yml Thu Jan 13 13:21:03 2011 +0000 @@ -416,6 +416,7 @@ label_register: Đăng ký label_password_lost: Phục hồi mật mã label_home: Trang chính + label_home_heading: Trang chính label_my_page: Trang riêng label_my_account: Cá nhân label_my_projects: Dự án của bạn
--- a/config/locales/zh-TW.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/zh-TW.yml Thu Jan 13 13:21:03 2011 +0000 @@ -565,6 +565,7 @@ label_login_with_open_id_option: 或使用 OpenID 登入 label_password_lost: 遺失密碼 label_home: 網站首頁 + label_home_heading: 網站首頁 label_my_page: 帳戶首頁 label_my_account: 我的帳戶 label_my_projects: 我的專案
--- a/config/locales/zh.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/locales/zh.yml Thu Jan 13 13:21:03 2011 +0000 @@ -471,6 +471,7 @@ label_login_with_open_id_option: 或使用OpenID登录 label_password_lost: 忘记密码 label_home: 主页 + label_home_heading: 主页 label_my_page: 我的工作台 label_my_account: 我的帐号 label_my_projects: 我的项目
--- a/config/settings.yml Thu Jan 13 12:53:21 2011 +0000 +++ b/config/settings.yml Thu Jan 13 13:21:03 2011 +0000 @@ -25,6 +25,10 @@ default: Project management welcome_text: default: +tipoftheday_text: + default: +notifications_text: + default: login_required: default: 0 self_registration:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/migrate/20101123161346_create_ssamr_user_details.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,14 @@ +class CreateSsamrUserDetails < ActiveRecord::Migration + def self.up + create_table :ssamr_user_details do |t| + t.integer :user_id + t.text :description + t.text :university + end + end + + def self.down + drop_table :ssamr_user_details + end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/mercurial/redminehelper.py Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,91 @@ +# redminehelper: Redmine helper extension for Mercurial +# it's a draft to show a possible way to explore repository by the Redmine overhaul patch +# see: http://www.redmine.org/issues/4455 +# +# Copyright 2010 Alessio Franceschelli (alefranz.net) +# Copyright 2010 Yuya Nishihara <yuya@tcha.org> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +'''command to list revision of each file +''' + +import re, time +from mercurial import cmdutil, commands, node, error + +SPECIAL_TAGS = ('tip',) + +def rhsummary(ui, repo, **opts): + """output the summary of the repository""" + # see mercurial/commands.py:tip + ui.write(':tip: rev node\n') + tipctx = repo[len(repo) - 1] + ui.write('%d %s\n' % (tipctx.rev(), tipctx)) + + # see mercurial/commands.py:root + ui.write(':root: path\n') + ui.write(repo.root + '\n') + + # see mercurial/commands.py:tags + ui.write(':tags: rev node name\n') + for t, n in reversed(repo.tagslist()): + if t in SPECIAL_TAGS: + continue + try: + r = repo.changelog.rev(n) + except error.LookupError: + r = -1 + ui.write('%d %s %s\n' % (r, node.short(n), t)) + + # see mercurial/commands.py:branches + def iterbranches(): + for t, n in repo.branchtags().iteritems(): + yield t, n, repo.changelog.rev(n) + + ui.write(':branches: rev node name\n') + for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True): + if repo.lookup(r) in repo.branchheads(t, closed=False): + ui.write('%d %s %s\n' % (r, node.short(n), t)) # only open branch + +def rhentries(ui, repo, path='', **opts): + """output the entries of the specified directory""" + rev = opts.get('rev') + pathprefix = (path.rstrip('/') + '/').lstrip('/') + + # TODO: clean up + dirs, files = {}, {} + mf = repo[rev].manifest() + for f in repo[rev]: + if not f.startswith(pathprefix): + continue + + name = re.sub(r'/.*', '', f[len(pathprefix):]) + if '/' in f[len(pathprefix):]: + dirs[name] = (name,) + else: + try: + fctx = repo.filectx(f, fileid=mf[f]) + ctx = fctx.changectx() + tm, tzoffset = ctx.date() + localtime = int(tm) + tzoffset - time.timezone + files[name] = (ctx.rev(), node.short(ctx.node()), localtime, + fctx.size(), name) + except LookupError: # TODO: when this occurs? + pass + + ui.write(':dirs: name\n') + for n, v in sorted(dirs.iteritems(), key=lambda e: e[0]): + ui.write(' '.join(v) + '\n') + + ui.write(':files: rev node time size name\n') + for n, v in sorted(files.iteritems(), key=lambda e: e[0]): + ui.write(' '.join(str(e) for e in v) + '\n') + + +cmdtable = { + 'rhsummary': (rhsummary, [], 'hg rhsummary'), + 'rhentries': (rhentries, + [('r', 'rev', '', 'show the specified revision')], + 'hg rhentries [path]'), +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/svn/SoundSoftware.pm Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,422 @@ +package Apache::Authn::SoundSoftware; + +=head1 Apache::Authn::SoundSoftware + +SoundSoftware - a mod_perl module for Apache authentication against a +Redmine database and optional LDAP implementing the access control +rules required for the SoundSoftware.ac.uk repository site. + +=head1 SYNOPSIS + +This module is closely based on the Redmine.pm authentication module +provided with Redmine. It is intended to be used for authentication +in front of a repository service such as hgwebdir. + +Requirements: + +1. Clone/pull from repo for public project: Any user, no +authentication required + +2. Clone/pull from repo for private project: Project members only + +3. Push to repo for public project: "Permitted" users only (this +probably means project members who are also identified in the hgrc web +section for the repository and so will be approved by hgwebdir?) + +4. Push to repo for private project: "Permitted" users only (as above) + +=head1 INSTALLATION + +Debian/ubuntu: + + apt-get install libapache-dbi-perl libapache2-mod-perl2 \ + libdbd-mysql-perl libauthen-simple-ldap-perl libio-socket-ssl-perl + +Note that LDAP support is hardcoded "on" in this script (it is +optional in the original Redmine.pm). + +=head1 CONFIGURATION + + ## This module has to be in your perl path + ## eg: /usr/local/lib/site_perl/Apache/Authn/SoundSoftware.pm + PerlLoadModule Apache::Authn::SoundSoftware + + # Example when using hgwebdir + ScriptAlias / "/var/hg/hgwebdir.cgi/" + + <Location /> + AuthName "Mercurial" + AuthType Basic + Require valid-user + PerlAccessHandler Apache::Authn::SoundSoftware::access_handler + PerlAuthenHandler Apache::Authn::SoundSoftware::authen_handler + SoundSoftwareDSN "DBI:mysql:database=redmine;host=localhost" + SoundSoftwareDbUser "redmine" + SoundSoftwareDbPass "password" + Options +ExecCGI + AddHandler cgi-script .cgi + ## Optional where clause (fulltext search would be slow and + ## database dependant). + # SoundSoftwareDbWhereClause "and members.role_id IN (1,2)" + ## Optional prefix for local repository URLs + # SoundSoftwareRepoPrefix "/var/hg/" + </Location> + +See the original Redmine.pm for further configuration notes. + +=cut + +use strict; +use warnings FATAL => 'all', NONFATAL => 'redefine'; + +use DBI; +use Digest::SHA1; +use Authen::Simple::LDAP; +use Apache2::Module; +use Apache2::Access; +use Apache2::ServerRec qw(); +use Apache2::RequestRec qw(); +use Apache2::RequestUtil qw(); +use Apache2::Const qw(:common :override :cmd_how); +use APR::Pool (); +use APR::Table (); + +my @directives = ( + { + name => 'SoundSoftwareDSN', + req_override => OR_AUTHCFG, + args_how => TAKE1, + errmsg => 'Dsn in format used by Perl DBI. eg: "DBI:Pg:dbname=databasename;host=my.db.server"', + }, + { + name => 'SoundSoftwareDbUser', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, + { + name => 'SoundSoftwareDbPass', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, + { + name => 'SoundSoftwareDbWhereClause', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, + { + name => 'SoundSoftwareRepoPrefix', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, +); + +sub SoundSoftwareDSN { + my ($self, $parms, $arg) = @_; + $self->{SoundSoftwareDSN} = $arg; + my $query = "SELECT + hashed_password, auth_source_id, permissions + FROM members, projects, users, roles, member_roles + WHERE + projects.id=members.project_id + AND member_roles.member_id=members.id + AND users.id=members.user_id + AND roles.id=member_roles.role_id + AND users.status=1 + AND login=? + AND identifier=? "; + $self->{SoundSoftwareQuery} = trim($query); +} + +sub SoundSoftwareDbUser { set_val('SoundSoftwareDbUser', @_); } +sub SoundSoftwareDbPass { set_val('SoundSoftwareDbPass', @_); } +sub SoundSoftwareDbWhereClause { + my ($self, $parms, $arg) = @_; + $self->{SoundSoftwareQuery} = trim($self->{SoundSoftwareQuery}.($arg ? $arg : "")." "); +} + +sub SoundSoftwareRepoPrefix { + my ($self, $parms, $arg) = @_; + if ($arg) { + $self->{SoundSoftwareRepoPrefix} = $arg; + } +} + +sub trim { + my $string = shift; + $string =~ s/\s{2,}/ /g; + return $string; +} + +sub set_val { + my ($key, $self, $parms, $arg) = @_; + $self->{$key} = $arg; +} + +Apache2::Module::add(__PACKAGE__, \@directives); + + +my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/; + +sub access_handler { + my $r = shift; + + print STDERR "SoundSoftware.pm: In access handler\n"; + + unless ($r->some_auth_required) { + $r->log_reason("No authentication has been configured"); + return FORBIDDEN; + } + + my $method = $r->method; + + print STDERR "SoundSoftware.pm: Method: $method, uri " . $r->uri . ", location " . $r->location . "\n"; + print STDERR "SoundSoftware.pm: Accept: " . $r->headers_in->{Accept} . "\n"; + + if (!defined $read_only_methods{$method}) { + print STDERR "SoundSoftware.pm: Method is not read-only, authentication handler required\n"; + return OK; + } + + my $dbh = connect_database($r); + + my $project_id = get_project_identifier($dbh, $r); + my $status = get_project_status($dbh, $project_id, $r); + + $dbh->disconnect(); + undef $dbh; + + if ($status == 0) { # nonexistent + print STDERR "SoundSoftware.pm: Project does not exist, refusing access\n"; + return FORBIDDEN; + } elsif ($status == 1) { # public + print STDERR "SoundSoftware.pm: Project is public, no restriction here\n"; + $r->set_handlers(PerlAuthenHandler => [\&OK]) + } else { # private + print STDERR "SoundSoftware.pm: Project is private, authentication handler required\n"; + } + + return OK +} + +sub authen_handler { + my $r = shift; + + print STDERR "SoundSoftware.pm: In authentication handler\n"; + + my $dbh = connect_database($r); + + my $project_id = get_project_identifier($dbh, $r); + my $realm = get_realm($dbh, $project_id, $r); + $r->auth_name($realm); + + my ($res, $redmine_pass) = $r->get_basic_auth_pw(); + unless ($res == OK) { + $dbh->disconnect(); + undef $dbh; + return $res; + } + + print STDERR "SoundSoftware.pm: User is " . $r->user . ", got password\n"; + + my $permitted = is_permitted($dbh, $project_id, $r->user, $redmine_pass, $r); + + $dbh->disconnect(); + undef $dbh; + + if ($permitted) { + return OK; + } else { + print STDERR "SoundSoftware.pm: Not permitted\n"; + $r->note_auth_failure(); + return AUTH_REQUIRED; + } +} + +sub get_project_status { + my $dbh = shift; + my $project_id = shift; + my $r = shift; + + if (!defined $project_id or $project_id eq '') { + return 0; # nonexistent + } + + my $sth = $dbh->prepare( + "SELECT is_public FROM projects WHERE projects.identifier = ?;" + ); + + $sth->execute($project_id); + my $ret = 0; # nonexistent + if (my @row = $sth->fetchrow_array) { + if ($row[0] eq "1" || $row[0] eq "t") { + $ret = 1; # public + } else { + $ret = 2; # private + } + } + $sth->finish(); + undef $sth; + + $ret; +} + +sub is_permitted { + my $dbh = shift; + my $project_id = shift; + my $redmine_user = shift; + my $redmine_pass = shift; + my $r = shift; + + my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass); + + my $cfg = Apache2::Module::get_config + (__PACKAGE__, $r->server, $r->per_dir_config); + + my $query = $cfg->{SoundSoftwareQuery}; + my $sth = $dbh->prepare($query); + $sth->execute($redmine_user, $project_id); + + my $ret; + while (my ($hashed_password, $auth_source_id, $permissions) = $sth->fetchrow_array) { + + # Test permissions for this user before we verify credentials + # -- if the user is not permitted this action anyway, there's + # not much point in e.g. contacting the LDAP + + my $method = $r->method; + + if ((defined $read_only_methods{$method} && $permissions =~ /:browse_repository/) + || $permissions =~ /:commit_access/) { + + # User would be permitted this action, if their + # credentials checked out -- test those now + + print STDERR "SoundSoftware.pm: User $redmine_user has required role, checking credentials\n"; + + unless ($auth_source_id) { + if ($hashed_password eq $pass_digest) { + print STDERR "SoundSoftware.pm: User $redmine_user authenticated via password\n"; + $ret = 1; + last; + } + } else { + my $sthldap = $dbh->prepare( + "SELECT host,port,tls,account,account_password,base_dn,attr_login FROM auth_sources WHERE id = ?;" + ); + $sthldap->execute($auth_source_id); + while (my @rowldap = $sthldap->fetchrow_array) { + my $ldap = Authen::Simple::LDAP->new( + host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0], + port => $rowldap[1], + basedn => $rowldap[5], + binddn => $rowldap[3] ? $rowldap[3] : "", + bindpw => $rowldap[4] ? $rowldap[4] : "", + filter => "(".$rowldap[6]."=%s)" + ); + if ($ldap->authenticate($redmine_user, $redmine_pass)) { + print STDERR "SoundSoftware.pm: User $redmine_user authenticated via LDAP\n"; + $ret = 1; + } + } + $sthldap->finish(); + undef $sthldap; + } + } else { + print STDERR "SoundSoftware.pm: User $redmine_user lacks required role for this project\n"; + } + } + + $sth->finish(); + undef $sth; + + $ret; +} + +sub get_project_identifier { + my $dbh = shift; + my $r = shift; + + my $location = $r->location; + my ($repo) = $r->uri =~ m{$location/*([^/]+)}; + + return $repo if (!$repo); + + $repo =~ s/[^a-zA-Z0-9\._-]//g; + + # The original Redmine.pm returns the string just calculated as + # the project identifier. That won't do for us -- we may have + # (and in fact already do have, in our test instance) projects + # whose repository names differ from the project identifiers. + + # This is a rather fundamental change because it means that almost + # every request needs more than one database query -- which + # prompts us to start passing around $dbh instead of connecting + # locally within each function as is done in Redmine.pm. + + my $sth = $dbh->prepare( + "SELECT projects.identifier FROM projects, repositories WHERE repositories.project_id = projects.id AND repositories.url LIKE ?;" + ); + + my $cfg = Apache2::Module::get_config + (__PACKAGE__, $r->server, $r->per_dir_config); + + my $prefix = $cfg->{SoundSoftwareRepoPrefix}; + if (!defined $prefix) { $prefix = '%/'; } + + my $identifier = ''; + + $sth->execute($prefix . $repo); + my $ret = 0; + if (my @row = $sth->fetchrow_array) { + $identifier = $row[0]; + } + $sth->finish(); + undef $sth; + + print STDERR "SoundSoftware.pm: Repository '$repo' belongs to project '$identifier'\n"; + + $identifier; +} + +sub get_realm { + my $dbh = shift; + my $project_id = shift; + my $r = shift; + + my $sth = $dbh->prepare( + "SELECT projects.name FROM projects WHERE projects.identifier = ?;" + ); + + my $name = $project_id; + + $sth->execute($project_id); + my $ret = 0; + if (my @row = $sth->fetchrow_array) { + $name = $row[0]; + } + $sth->finish(); + undef $sth; + + # be timid about characters not permitted in auth realm and revert + # to project identifier if any are found + if ($name =~ m/[^\w\d\s\._-]/) { + $name = $project_id; + } + + my $realm = '"Mercurial repository for ' . "'$name'" . '"'; + + $realm; +} + +sub connect_database { + my $r = shift; + + my $cfg = Apache2::Module::get_config + (__PACKAGE__, $r->server, $r->per_dir_config); + + return DBI->connect($cfg->{SoundSoftwareDSN}, + $cfg->{SoundSoftwareDbUser}, + $cfg->{SoundSoftwareDbPass}); +} + +1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/svn/reposman-soundsoftware.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,350 @@ +#!/usr/bin/env ruby + +# == Synopsis +# +# reposman: manages your repositories with Redmine +# +# == Usage +# +# reposman [OPTIONS...] -s [DIR] -r [HOST] +# +# Examples: +# reposman --svn-dir=/var/svn --redmine-host=redmine.example.net --scm subversion +# reposman -s /var/git -r redmine.example.net -u http://svn.example.net --scm git +# +# == Arguments (mandatory) +# +# -s, --svn-dir=DIR use DIR as base directory for svn repositories +# -r, --redmine-host=HOST assume Redmine is hosted on HOST. Examples: +# -r redmine.example.net +# -r http://redmine.example.net +# -r https://example.net/redmine +# -k, --key=KEY use KEY as the Redmine API key +# +# == Options +# +# -o, --owner=OWNER owner of the repository. using the rails login +# allow user to browse the repository within +# Redmine even for private project. If you want to +# share repositories through Redmine.pm, you need +# to use the apache owner. +# -g, --group=GROUP group of the repository. (default: root) +# --scm=SCM the kind of SCM repository you want to create (and +# register) in Redmine (default: Subversion). +# reposman is able to create Git and Subversion +# repositories. For all other kind, you must specify +# a --command option +# -u, --url=URL the base url Redmine will use to access your +# repositories. This option is used to automatically +# register the repositories in Redmine. The project +# identifier will be appended to this url. Examples: +# -u https://example.net/svn +# -u file:///var/svn/ +# if this option isn't set, reposman will register +# the repositories with local file paths in Redmine +# -c, --command=COMMAND use this command instead of "svnadmin create" to +# create a repository. This option can be used to +# create repositories other than subversion and git +# kind. +# This command override the default creation for git +# and subversion. +# --http-user=USER User for HTTP Basic authentication with Redmine WS +# --http-pass=PASSWORD Password for Basic authentication with Redmine WS +# -t, --test only show what should be done +# -h, --help show help and exit +# -v, --verbose verbose +# -V, --version print version and exit +# -q, --quiet no log +# +# == References +# +# You can find more information on the redmine's wiki : http://www.redmine.org/wiki/redmine/HowTos + + +require 'getoptlong' +require 'rdoc/usage' +require 'find' +require 'etc' + +Version = "1.3" +SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem ) + +opts = GetoptLong.new( + ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT], + ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT], + ['--key', '-k', GetoptLong::REQUIRED_ARGUMENT], + ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT], + ['--group', '-g', GetoptLong::REQUIRED_ARGUMENT], + ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT], + ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT], + ['--scm', GetoptLong::REQUIRED_ARGUMENT], + ['--http-user', GetoptLong::REQUIRED_ARGUMENT], + ['--http-pass', GetoptLong::REQUIRED_ARGUMENT], + ['--test', '-t', GetoptLong::NO_ARGUMENT], + ['--verbose', '-v', GetoptLong::NO_ARGUMENT], + ['--version', '-V', GetoptLong::NO_ARGUMENT], + ['--help' , '-h', GetoptLong::NO_ARGUMENT], + ['--quiet' , '-q', GetoptLong::NO_ARGUMENT] + ) + +$verbose = 0 +$quiet = false +$redmine_host = '' +$repos_base = '' +$http_user = '' +$http_pass = '' +$svn_owner = 'root' +$svn_group = 'root' +$use_groupid = true +$svn_url = false +$test = false +$scm = 'Subversion' + +def log(text, options={}) + level = options[:level] || 0 + puts text unless $quiet or level > $verbose + exit 1 if options[:exit] +end + +def system_or_raise(command) + raise "\"#{command}\" failed" unless system command +end + +module SCM + + module Subversion + def self.create(path) + system_or_raise "svnadmin create #{path}" + end + end + + module Git + def self.create(path) + Dir.mkdir path + Dir.chdir(path) do + system_or_raise "git --bare init --shared" + system_or_raise "git update-server-info" + end + end + end + +end + +begin + opts.each do |opt, arg| + case opt + when '--svn-dir'; $repos_base = arg.dup + when '--redmine-host'; $redmine_host = arg.dup + when '--key'; $api_key = arg.dup + when '--owner'; $svn_owner = arg.dup; $use_groupid = false; + when '--group'; $svn_group = arg.dup; $use_groupid = false; + when '--url'; $svn_url = arg.dup + when '--scm'; $scm = arg.dup.capitalize; log("Invalid SCM: #{$scm}", :exit => true) unless SUPPORTED_SCM.include?($scm) + when '--http-user'; $http_user = arg.dup + when '--http-pass'; $http_pass = arg.dup + when '--command'; $command = arg.dup + when '--verbose'; $verbose += 1 + when '--test'; $test = true + when '--version'; puts Version; exit + when '--help'; RDoc::usage + when '--quiet'; $quiet = true + end + end +rescue + exit 1 +end + +if $test + log("running in test mode") +end + +# Make sure command is overridden if SCM vendor is not handled internally (for the moment Subversion and Git) +if $command.nil? + begin + scm_module = SCM.const_get($scm) + rescue + log("Please use --command option to specify how to create a #{$scm} repository.", :exit => true) + end +end + +$svn_url += "/" if $svn_url and not $svn_url.match(/\/$/) + +if ($redmine_host.empty? or $repos_base.empty?) + RDoc::usage +end + +unless File.directory?($repos_base) + log("directory '#{$repos_base}' doesn't exists", :exit => true) +end + +begin + require 'active_resource' +rescue LoadError + log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true) +end + +class Project < ActiveResource::Base + self.headers["User-agent"] = "Redmine repository manager/#{Version}" +end + +log("querying Redmine for projects...", :level => 1); + +$redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://") +$redmine_host.gsub!(/\/$/, '') + +Project.site = "#{$redmine_host}/sys"; +Project.user = $http_user; +Project.password = $http_pass; + +begin + # Get all active projects that have the Repository module enabled + projects = Project.find(:all, :params => {:key => $api_key}) +rescue => e + log("Unable to connect to #{Project.site}: #{e}", :exit => true) +end + +if projects.nil? + log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true) +end + +log("retrieved #{projects.size} projects", :level => 1) + +def set_owner_and_rights(project, repos_path, &block) + if RUBY_PLATFORM =~ /mswin/ + yield if block_given? + else + uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid) + right = project.is_public ? 02775 : 02770 + yield if block_given? + Find.find(repos_path) do |f| + File.chmod right, f + File.chown uid, gid, f + end + end +end + +def other_read_right?(file) + (File.stat(file).mode & 0007).zero? ? false : true +end + +def owner_name(file) + mswin? ? + $svn_owner : + Etc.getpwuid( File.stat(file).uid ).name +end + +def mswin? + (RUBY_PLATFORM =~ /(:?mswin|mingw)/) || (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i) +end + +projects.each do |project| + log("treating project #{project.name}", :level => 1) + + if project.identifier.empty? + log("\tno identifier for project #{project.name}") + next + elsif not project.identifier.match(/^[a-z0-9\-]+$/) + log("\tinvalid identifier for project #{project.name} : #{project.identifier}"); + next; + end + + repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR) + + create_repos = false + + # Logic required for SoundSoftware.ac.uk repositories: + # + # * If the project has a repository path declared already, + # - if it's a local path, + # - if it does not exist + # - if it has the right root + # - create it + # - else + # - leave alone (remote repository) + # * else + # - create repository with same name as project + # - set to project + + if project.respond_to?(:repository) + + repos_url = project.repository.url; + log("\texisting url for project #{project.identifier} is #{repos_url}"); + + if repos_url.match(/^file:\//) || repos_url.match(/^\//) + + repos_url = repos_url.gsub(/^file:\/*/, "/"); + log("\tthis is a local file path, at #{repos_url}"); + + if repos_url.slice(0, $repos_base.length) != $repos_base + log("\tit is in the wrong place: replacing it"); + # leave repos_path set to our original suggestion + create_repos = true + else + if !File.directory?(repos_url) + log("\tit doesn't exist; we should create it"); + repos_path = repos_url + create_repos = true + else + log("\tit exists and is in the right place"); + end + end + else + log("\tthis is a remote path, leaving alone"); + end + else + log("\tproject #{project.identifier} has no repository registered") +# if File.directory?(repos_path) +# log("\trepository path #{repos_path} already exists, not creating") +# else + create_repos = true +# end + end + + if create_repos + + registration_url = repos_path + if $svn_url + registration_url = "#{$svn_url}#{project.identifier}" + end + + if $test + log("\tproposal: create repository #{repos_path}") + log("\tproposal: register repository #{repos_path} in Redmine with vendor #{$scm}, url #{registration_url}") + next + end + +# No -- we need "other" users to be able to read it. Access control +# is not handled through Unix user id anyway +# project.is_public ? File.umask(0002) : File.umask(0007) + File.umask(0002) + + log("\taction: create repository #{repos_path}") + + begin + if !File.directory?(repos_path) + set_owner_and_rights(project, repos_path) do + if scm_module.nil? + log("\trunning command: #{$command} #{repos_path}") + system_or_raise "#{$command} #{repos_path}" + else + scm_module.create(repos_path) + end + end + end + rescue => e + log("\tunable to create #{repos_path} : #{e}\n") + next + end + + begin + log("\taction: register repository #{repos_path} in Redmine with vendor #{$scm}, url #{registration_url}"); + project.post(:repository, :vendor => $scm, :repository => {:url => "#{registration_url}"}, :key => $api_key) + rescue => e + log("\trepository #{repos_path} not registered in Redmine: #{e.message}"); + end + + log("\trepository #{repos_path} created"); + end + +end +
--- a/extra/svn/reposman.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/extra/svn/reposman.rb Thu Jan 13 13:21:03 2011 +0000 @@ -48,6 +48,8 @@ # kind. # This command override the default creation for git # and subversion. +# --http-user=USER User for HTTP Basic authentication with Redmine WS +# --http-pass=PASSWORD Password for Basic authentication with Redmine WS # -f, --force force repository creation even if the project # repository is already declared in Redmine # -t, --test only show what should be done @@ -78,6 +80,8 @@ ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT], ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT], ['--scm', GetoptLong::REQUIRED_ARGUMENT], + ['--http-user', GetoptLong::REQUIRED_ARGUMENT], + ['--http-pass', GetoptLong::REQUIRED_ARGUMENT], ['--test', '-t', GetoptLong::NO_ARGUMENT], ['--force', '-f', GetoptLong::NO_ARGUMENT], ['--verbose', '-v', GetoptLong::NO_ARGUMENT], @@ -90,6 +94,8 @@ $quiet = false $redmine_host = '' $repos_base = '' +$http_user = '' +$http_pass = '' $svn_owner = 'root' $svn_group = 'root' $use_groupid = true @@ -138,6 +144,8 @@ when '--group'; $svn_group = arg.dup; $use_groupid = false; when '--url'; $svn_url = arg.dup when '--scm'; $scm = arg.dup.capitalize; log("Invalid SCM: #{$scm}", :exit => true) unless SUPPORTED_SCM.include?($scm) + when '--http-user'; $http_user = arg.dup + when '--http-pass'; $http_pass = arg.dup when '--command'; $command = arg.dup when '--verbose'; $verbose += 1 when '--test'; $test = true @@ -190,6 +198,8 @@ $redmine_host.gsub!(/\/$/, '') Project.site = "#{$redmine_host}/sys"; +Project.user = $http_user; +Project.password = $http_pass; begin # Get all active projects that have the Repository module enabled @@ -309,4 +319,4 @@ end end - \ No newline at end of file +
--- a/lib/redmine/info.rb Thu Jan 13 12:53:21 2011 +0000 +++ b/lib/redmine/info.rb Thu Jan 13 13:21:03 2011 +0000 @@ -3,7 +3,7 @@ class << self def app_name; 'Redmine' end def url; 'http://www.redmine.org/' end - def help_url; 'http://www.redmine.org/guide' end + def help_url; '/projects/soundsoftware-site/wiki/Help' end def versioned_name; "#{app_name} #{Redmine::VERSION}" end # Creates the url string to a specific Redmine issue
--- a/lib/redmine/scm/adapters/mercurial/hg-template-0.9.5.tmpl Thu Jan 13 12:53:21 2011 +0000 +++ b/lib/redmine/scm/adapters/mercurial/hg-template-0.9.5.tmpl Thu Jan 13 13:21:03 2011 +0000 @@ -9,4 +9,4 @@ file_copy = '<path-copied copyfrom-path="{source|urlescape}">{name|urlescape}</path-copied>\n' tag = '<tag>{tag|escape}</tag>\n' header='<?xml version="1.0" encoding="UTF-8" ?>\n<log>\n\n' -# footer="</log>" \ No newline at end of file +footer='</log>'
--- a/lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl Thu Jan 13 12:53:21 2011 +0000 +++ b/lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl Thu Jan 13 13:21:03 2011 +0000 @@ -9,4 +9,4 @@ file_copy = '<path-copied copyfrom-path="{source|urlescape}">{name|urlescape}</path-copied>\n' tag = '<tag>{tag|escape}</tag>\n' header='<?xml version="1.0" encoding="UTF-8" ?>\n<log>\n\n' -# footer="</log>" +footer='</log>'
--- a/public/stylesheets/application.css Thu Jan 13 12:53:21 2011 +0000 +++ b/public/stylesheets/application.css Thu Jan 13 13:21:03 2011 +0000 @@ -351,7 +351,7 @@ ul.projects li.root { list-style-type:none; margin-bottom: 1em; } ul.projects li.child { list-style-type:none; margin-top: 1em;} ul.projects div.root a.project { /* font-family: "Trebuchet MS", Verdana, sans-serif; */ font-weight: bold; font-size: 16px; margin: 0 0 10px 0; } -.my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; } +/* .my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; } */ #tracker_project_ids ul { margin: 0; padding-left: 1em; } #tracker_project_ids li { list-style-type:none; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/themes/soundsoftware/stylesheets/application.css Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,118 @@ +@import url(../../../stylesheets/application.css); +@import url(fonts.css); + +/* Colours: + + #be5700 link (orange) + + #3e442c text (dark green) + (OK for headings, but small text is easier to read in black) + + #ffa801 logo (yellow) + + #525a38 logotype (olive) + + #fdfaf0 background (cream) + + #fdfbf5 alternate background (lighter cream) + + #ffe69b highlight (light yellow) + + #a9b680 detail (light green) +*/ + +body { + background: #fdfbf5; + color: #000; + margin: 0; + margin-bottom: 40px; +/* font-size: 95%; */ +} + +h1 { + color: #3e442c; + font-family: GilliusADFNo2, 'Gill Sans', Tahoma, sans-serif; + font-weight: normal; +} + +body,p,h2,h3,h4,li,table,.wiki h1 { + font-family: DroidSans, 'Liberation Sans', tahoma, verdana, sans-serif; */ +} + +h2,h3,h4,.wiki h1 { + color: #3e442c; +} + +h2,.wiki h1 { + font-size: 1.8em; +} + +.box { + padding: 6px; + margin-bottom: 10px; + background-color: #fdfaf0; + color: #3e442c; + line-height: 1.5em; + border: 1px solid #a9b680; + border-left: 4px solid #a9b680; +} + +.odd {background-color:#fdf7e4;} +.even {background-color: #fdfaf0;} + +#content .tabs { margin-bottom: 0; } + +table.list th { background-color: #fdfaf0; border-bottom: 1px solid #a9b680; } +table.list { border: 1px solid #a9b680; /* border-left: 4px solid #a9b680; */ } +tr.entry { border-left: 1px solid #a9b680; border-right: 1px solid #a9b680; } +tr.entry:last-child { border-bottom: 1px solid #a9b680; } + +#top-menu { position: absolute; top: 0; z-index: 1; left: 0px; width: 100%; font-size: 90%; /* height: 2em; */ margin: 0; padding: 0; padding-top: 0.5em; background-color: #3e442c; } +#top-menu ul { margin-left: 10px; } +#top-menu a { font-weight: bold; } +#header { position: absolute; z-index: 0; top: 0; width: 100%; background: #fdfbf5; border-bottom: 2px solid #a9b680; /* height:80px; */ padding: 20px 0 0.5em 0; margin-bottom: 0; } +#header a { color: #be5700; } +#header h1 { color: #525a38; margin-top: 25px; font-size: 3em; font-weight: normal; margin-left: 10px; } +.header-general h1 { + background: url('soundsoftware-logo-title-only-transparent.png') no-repeat 0 0; + text-indent: -9999px; + width: 446px; + height: 34px; + } +#quick-search { margin-right: 6px; margin-top: 1em; color: #000; } +#main-menu { position: absolute; top: 100px; /* background-color: #be5700; */ left: 0; border-top: 0; width: 100%;/* height: 1.82em; */ padding: 0; margin: 0; border: 0; } +#main-menu li { margin: 0; padding: 0; } +#main-menu li a { background-color: #fdfbf5; color: #be5700; border-right: 1px solid #a9b680; font-size: 97%; padding: 0em 8px 0.2em 10px; font-weight: normal; } +#main-menu li:last-child a { border-right: 0; } +#main-menu li a:hover { background-color: #fdfbf5; color: #be5700; text-decoration: underline; } +#main-menu li a.selected, #main-menu li a.selected:hover { background-color: #fdfbf5; color: #3e442c; } + +#footer { background-color: #fdfbf5; border: 0; border-top: 2px solid #a9b680; color: #3e442c; text-align: right; } +#footer a { color: #be5700; font-weight: bold; } + +#main { margin-top: 135px; font:95%; background: #fdfaf0; } +#main a { font-weight: medium; color: #be5700;} +#main a:hover { color: #be5700; text-decoration: underline; } +#content { background: #fdfbf5; } +/*#content .tabs ul { bottom:-1px; } +*/ +h2, h3, h4, .wiki h1, .wiki h2, .wiki h3 { border-bottom: 0px; } +/*h2, .wiki h1 { letter-spacing:-1px; } +*/ +h4 { border-bottom: dotted 1px #c0c0c0; } + +div.issue { background: #fdfaf0; border: 1px solid #a9b680; border-left: 4px solid #a9b680; } + +#top-menu a.home, #top-menu a.my-page, #top-menu a.projects, #top-menu a.administration, #top-menu a.help { + background-position: 0% 40%; + background-repeat: no-repeat; + padding-left: 20px; + padding-top: 2px; + padding-bottom: 3px; +} + +#top-menu a.home { background-image: url(../images/home.png); } +#top-menu a.my-page { background-image: url(../../../images/user.png); } +#top-menu a.projects { background-image: url(../../../images/projects.png); } +#top-menu a.administration { background-image: url(../images/wrench.png); } +#top-menu a.help { background-image: url(../../../images/help.png); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/themes/soundsoftware/stylesheets/fonts.css Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,83 @@ + +/* Font pack generated by FontSquirrel */ + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-bolditalic-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-bolditalic-webfont.woff') format('woff'), url('fonts/gilliusadfno2-bolditalic-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-BoldItalic.otf') format('opentype'), url('fonts/gilliusadfno2-bolditalic-webfont.svg#webfontLmhvPwzc') format('svg'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-italic-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-italic-webfont.woff') format('woff'), url('fonts/gilliusadfno2-italic-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-Italic.otf') format('opentype'), url('fonts/gilliusadfno2-italic-webfont.svg#webfonteHBtzgS0') format('svg'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-bold-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-bold-webfont.woff') format('woff'), url('fonts/gilliusadfno2-bold-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-Bold.otf') format('opentype'), url('fonts/gilliusadfno2-bold-webfont.svg#webfontntXmQMqk') format('svg'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-regular-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-regular-webfont.woff') format('woff'), url('fonts/gilliusadfno2-regular-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-Regular.otf') format('opentype'), url('fonts/gilliusadfno2-regular-webfont.svg#webfontvJUiAdi3') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-italic-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-italic-webfont.woff') format('woff'), url('fonts/liberationsans-italic-webfont.ttf') format('truetype'), url('fonts/liberationsans-italic-webfont.svg#webfontBdDf5JP3') format('svg'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-bolditalic-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-bolditalic-webfont.woff') format('woff'), url('fonts/liberationsans-bolditalic-webfont.ttf') format('truetype'), url('fonts/liberationsans-bolditalic-webfont.svg#webfontTNmZRY7v') format('svg'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-bold-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-bold-webfont.woff') format('woff'), url('fonts/liberationsans-bold-webfont.ttf') format('truetype'), url('fonts/liberationsans-bold-webfont.svg#webfontslkXRzon') format('svg'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-regular-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-regular-webfont.woff') format('woff'), url('fonts/liberationsans-regular-webfont.ttf') format('truetype'), url('fonts/liberationsans-regular-webfont.svg#webfontV0O783dY') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'DroidSans'; + src: url('fonts/DroidSans-webfont.eot'); + src: local('☺'), url('fonts/DroidSans-webfont.woff') format('woff'), url('fonts/DroidSans-webfont.ttf') format('truetype'), url('fonts/DroidSans-webfont.svg#webfontKYIQSBQk') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'DroidSans'; + src: url('fonts/DroidSans-Bold-webfont.eot'); + src: local('☺'), url('fonts/DroidSans-Bold-webfont.woff') format('woff'), url('fonts/DroidSans-Bold-webfont.ttf') format('truetype'), url('fonts/DroidSans-Bold-webfont.svg#webfontljpTCDjw') format('svg'); + font-weight: bold; + font-style: normal; +} +
Binary file public/themes/soundsoftware/stylesheets/soundsoftware-logo-title-only-transparent.png has changed
--- a/public/themes/ssamr/stylesheets/application.css Thu Jan 13 12:53:21 2011 +0000 +++ b/public/themes/ssamr/stylesheets/application.css Thu Jan 13 13:21:03 2011 +0000 @@ -20,6 +20,19 @@ src: url('DroidSans-Bold.ttf'); } +@font-face +{ + font-family: Gillius; + src: url('GilliusADFNo2-Regular.otf'); +} + +@font-face +{ + font-family: Gillius; + font-weight: bold; + src: url('GilliusADFNo2-Bold.otf'); +} + body { background: #ffffff; color: #404040;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/fixtures/ssamr_user_details.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# one: +# column: value +# +# two: +# column: value
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/ssamr_user_details_test.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,8 @@ +require 'test_helper' + +class SsamrUserDetailsTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "User Id should be correct" do + assert_equal user_id, user.id + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/README.rdoc Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,43 @@ += Redmine Checkout plugin + +Author:: Holger Just +URL:: http://dev.holgerjust.de/projects/redmine-checkout + +This plugin to Redmine adds a link to the actual repository to the GUI. + +This plugin includes ZeroClipboard[http://code.google.com/p/zeroclipboard/] +by Joseph Huckaby. This software is licensed under the +{GNU Lesser General Public License}[http://www.gnu.org/licenses/lgpl.html]. + +Copyright (c) 2009, 2010 Holger Just + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + += Installation + +The installation follows the standard installation path from +http://www.redmine.org/projects/redmine/wiki/Plugins + +1. Copy the software to the vendor/plugins directory. Make sure that the name + of the directory is redmine_checkout. +2. Run rake db:migrate_plugins RAILS_ENV=production +3. Restart Redmine
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/Rakefile Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby +require 'redmine_plugin_support' + +Dir[File.expand_path(File.dirname(__FILE__)) + "/lib/tasks/**/*.rake"].sort.each { |ext| load ext } + +RedminePluginSupport::Base.setup do |plugin| + plugin.project_name = 'redmine_checkout' + plugin.default_task = [:spec] + plugin.tasks = [:doc, :release, :clean, :spec, :stats] +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/projects/settings/_repository_checkout.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,54 @@ +<p><%= form.select(:checkout_overwrite, [ + [l(:general_text_Yes), "1"], + [l(:general_text_No), "0"] + ], + {}, + :onchange => <<-EOF + Effect.toggle($('checkout_settings'), 'slide', {duration:0.2}); + EOF + )%></p> + +<div id="checkout_settings" <%= 'style="display:none;"' unless form.object.checkout_overwrite? %>><fieldset> + <legend><%=l :label_checkout %></legend> + + <p><%= form.text_area :checkout_description, :cols => 60, :rows => 5, :class => 'wiki-edit', :label => :field_description %></p> + <%= wikitoolbar_for 'repository_checkout_description' %> + + <% if form.object.scm_name == 'Subversion' %> + <p><%= form.select :checkout_display_login,[ + [l(:label_display_login_none), ''], + [l(:label_display_login_username), 'username'], + [l(:label_display_login_password), 'password'] + ], + :label => :setting_checkout_display_login %></p> + <% end %> + + <p><%= form.check_box :checkout_display_command %></p> + + <% javascript_tag do %> + protocolForm = new Subform( + '<%= escape_javascript(render(:partial => "projects/settings/repository_checkout_protocol", :locals => {:protocol => Checkout::Protocol.new({:protocol => form.object.scm_name, :append_path => form.object.allow_subtree_checkout? ? 1: 0, :repository => form.object})})) %>', + <%= form.object.checkout_protocols.length %>, + 'checkout_protocol_table' + ); + <% end %> + <p><label><%=l :label_protocol_plural %></label><%=l :help_repository_checkout_protocols %></p> + <%= hidden_field_tag 'repository[checkout_protocols][-1][protocol]', 'empty' %> + <table class="list checkout_protocol_table"> + <thead><tr> + <th class="protocol_protocol" ><%= l(:setting_protocol)%></th> + <th class="protocol_command" ><%= l(:setting_checkout_command)%></th> + <th class="protocol_fixed_url" ><%= l(:setting_checkout_fixed_url) %></th> + <th class="protocol_access" ><%= l(:label_permissions) %></th> + <th class="protocol_append_path"><%= l(:label_append_path) %></th> + <th class="protocol_is_default" ><%= l(:label_default) %></th> + <th class="protocol_delete" ></th> + </tr></thead> + <tbody id="checkout_protocol_table"> + <% form.object.checkout_protocols.each_with_index do |protocol, index| %> + <%= render :partial => 'projects/settings/repository_checkout_protocol', :locals => {:protocol => protocol, :index => index, :classes => cycle('odd', 'even')} %> + <% end %> + </tbody> + </table> + <div style="text-align: right"><%= link_to_function l(:button_add_protocol), "protocolForm.add()", {:class => "icon icon-add"} %></div> +</fieldset></div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/projects/settings/_repository_checkout_protocol.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,18 @@ +<% + index ||= "--INDEX--" + classes ||= "" + + protocol = Checkout::Protocol.new(protocol) unless protocol.is_a? Checkout::Protocol +%> +<tr id="<%= "checkout_protocols_#{index}" %>" class="<%= classes %>" <%= 'style="display:none"' if index == '--INDEX--' %>> + <td class="protocol_protocol"><%= text_field_tag "repository[checkout_protocols][#{index}][protocol]", protocol.protocol, :size => 10 %></td> + <td class="protocol_command"><%= text_field_tag "repository[checkout_protocols][#{index}][command]", protocol.command, :size => 15 %></td> + <td class="protocol_fixed_url"><%= text_field_tag "repository[checkout_protocols][#{index}][fixed_url]", protocol.fixed_url, :size => 60 %></td> + <td class="protocol_access"><%= select_tag "repository[checkout_protocols][#{index}][access]", options_for_select([ + [l(:label_access_read_write), 'read+write'], + [l(:label_access_read_only), 'read-only'], + [l(:label_access_permission), 'permission']], protocol.access) %></td> + <td class="protocol_append_path"><%= check_box_tag "repository[checkout_protocols][#{index}][append_path]", 1, protocol.append_path? %></td> + <td class="protocol_is_default"><%= check_box_tag "repository[checkout_protocols][#{index}][is_default]", 1, protocol.default? %></td> + <td class="protocol_delete"><%= image_to_function 'delete.png', "var e=$('checkout_protocols_#{index}');var parent=e.up(\"tbody\");e.remove();recalculate_even_odd(parent);return false" %></td> +</tr>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/redmine_checkout_hooks/_view_repositories_show_contextual.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,36 @@ +<div class="repository-info"> + <% if repository.checkout_description.present? %> + <div class="wiki<%= ' bottomline' if protocols.present? %>"><%= textilizable repository.checkout_description %></div> + <% end %> + <% if protocols.present? %> + <div id="checkout_box"> + <ul id="checkout_protocols"> + <% protocols.each do |p| -%> + <li> + <a <%= 'class="selected"' if p == default_protocol %> id="checkout_protocol_<%= p.protocol.to_s.underscore %>" data-permission="<%= p.access_rw(User.current) %>" href="<%= URI.escape p.url(checkout_path) %>"><%=h p.protocol %></a> + </li> + <% end -%> + </ul> + <%= text_field_tag :checkout_url, h(default_protocol.full_command(checkout_path)), :readonly => true %> + <%- if Setting.checkout_use_zero_clipboard? %> + <div id="clipboard_container" title="<%= l(:label_copy_to_clipboard) %>" style="display: none;"> + <div id="clipboard_button"><%= image_tag 'paste.png', :plugin => 'redmine_checkout' %></div> + </div> + <% end -%> + <% if default_protocol %><p><%=l :label_access_type, :type => l(default_protocol.access_label(User.current)) %></p><% end %> + + <% javascript_tag do %> + var checkout_access = $H({<%= protocols.inject([]){|r,p| r << "'checkout_protocol_#{p.protocol.to_s.underscore}': '#{l(p.access_label(User.current))}'"}.join(', ') %>}); + var checkout_commands = $H({<%= protocols.inject([]){|r,p| r << "'checkout_protocol_#{p.protocol.to_s.underscore}': '#{escape_javascript(p.full_command(checkout_path))}'"}.join(', ') %>}); + <%- if Setting.checkout_use_zero_clipboard? %>ZeroClipboard.setMoviePath( '<%= image_path('ZeroClipboard.swf', :plugin => 'redmine_checkout') %>' );<% end %> + <% end %> + </div> + <% end%> +</div> +<div style="clear: left"></div> + +<% content_for :header_tags do %> + <%= stylesheet_link_tag 'checkout', :plugin => 'redmine_checkout' %> + <%= javascript_include_tag 'checkout', :plugin => 'redmine_checkout' %> + <%= (javascript_include_tag 'ZeroClipboard', :plugin => 'redmine_checkout') if Setting.checkout_use_zero_clipboard? %> +<% end %> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_checkout.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,43 @@ +<% form_tag({:action => 'edit', :tab => 'checkout'}) do %> + +<% javascript_tag do %> +protocolForms = $H(); + +document.observe("dom:loaded", function() { + $('tab-content-checkout').select('fieldset.collapsed').each(function(e){ + e.down('div').hide(); + }); + <% + CheckoutHelper.supported_scm.select{|scm| Setting.enabled_scm.include?(scm)}.each do |scm| + next if Setting.send("checkout_overwrite_description_#{scm}?") + -%> + $('settings_checkout_description_<%= scm %>').up('div').up('div').hide(); + <%- end %> +}); +<% end %> + + +<div class="box tabular settings"> +<p><%= setting_check_box :checkout_display_checkout_info %></p> + +<p><%= setting_text_area :checkout_description_Abstract, :cols => 60, :rows => 5, :class => 'wiki-edit', :label => :field_description %></p> +<%= wikitoolbar_for 'settings_checkout_description_Abstract' %> + +<p><%= setting_check_box :checkout_use_zero_clipboard %></p> + +<% CheckoutHelper.supported_scm.select{|scm| Setting.enabled_scm.include?(scm)}.each do |scm| -%> +<fieldset class="collapsible collapsed"> + <legend onclick="toggleFieldset(this);"><%= "Repository::#{scm}".constantize.scm_name %></legend> + <div><%= render :partial => 'checkout_scm', :locals => {:scm => scm} %></div> +</fieldset> +<%- end %> + +</div> + +<%= submit_tag l(:button_save) %> +<%- end %> + +<% content_for :header_tags do %> + <%= javascript_include_tag 'subform', :plugin => 'redmine_checkout' %> + <%= stylesheet_link_tag 'checkout', :plugin => 'redmine_checkout' %> +<% end %>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_checkout_protocol.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,19 @@ +<% + index ||= "--INDEX--" + classes ||= "" + + protocol = Checkout::Protocol.new(protocol) unless protocol.is_a? Checkout::Protocol +%> +<tr id="<%= "checkout_protocols_#{scm}_#{index}" %>" class="<%= classes %>" <%= 'style="display:none"' if index == '--INDEX--' %>> + <td class="protocol_protocol" ><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][protocol]", protocol.protocol, :size => 10 %></td> + <td class="protocol_command" ><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][command]", protocol.command, :size => 15 %></td> + <td class="protocol_regex" ><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][regex]", protocol.regex, :size => 30 %></td> + <td class="protocol_regex_replacement"><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][regex_replacement]", protocol.regex_replacement, :size => 30 %></td> + <td class="protocol_access" ><%= select_tag "settings[checkout_protocols_#{scm}][#{index}][access]", options_for_select([ + [l(:label_access_read_write), 'read+write'], + [l(:label_access_read_only), 'read-only'], + [l(:label_access_permission), 'permission']], protocol.access) %></td> + <td class="protocol_append_path"><%= check_box_tag "settings[checkout_protocols_#{scm}][#{index}][append_path]", 1, protocol.append_path? %></td> + <td class="protocol_is_default"><%= check_box_tag "settings[checkout_protocols_#{scm}][#{index}][is_default]", 1, protocol.default? %></td> + <td class="protocol_delete"><%= image_to_function 'delete.png', "var e=$('checkout_protocols_#{scm}_#{index}');var parent=e.up(\"tbody\");e.remove();recalculate_even_odd(parent);return false" %></td> +</tr>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_checkout_scm.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,46 @@ +<div> + <p><%= setting_check_box "checkout_overwrite_description_#{scm}", :label => :setting_checkout_overwrite_description, :onclick => <<-EOF + Effect.toggle($('settings_checkout_description_#{scm}').up("div").up("div"), 'slide', {duration:0.2}); + EOF + %></p> + + <div> + <p><%= setting_text_area "checkout_description_#{scm}", :cols => 60, :rows => 5, :class => 'wiki-edit', :label => :field_description %></p> + <%= wikitoolbar_for "settings_checkout_description_#{scm}" %> + </div> + + <% if scm == 'Subversion' %> + <p><%= setting_select "checkout_display_login",[ + [l(:label_display_login_username), 'username'], + [l(:label_display_login_password), 'password'] + ], + :blank => :label_display_login_none %></p> + <% end %> + + <p><%= setting_check_box "checkout_display_command_#{scm}", :label => :field_checkout_display_command %></p> + + <% javascript_tag do %> + <% repo = "Repository::#{scm}".constantize %> + var subform = new Subform('<%= escape_javascript(render(:partial => "checkout_protocol", :locals => {:protocol => Checkout::Protocol.new({:protocol => repo.scm_name, :append_path => (repo.allow_subtree_checkout? ? '1' : '0'), :command => repo.checkout_default_command}), :scm => scm})) %>',<%= Setting.send("checkout_protocols_#{scm}").length %>,'settings_checkout_protocols_<%= scm %>'); + protocolForms.set('<%= scm %>', subform); + <% end %> + <p><label><%=l :label_protocol_plural %></label><%=l :help_checkout_protocols %></p> + <table class="list checkout_protocol_table"> + <thead><tr> + <th class="protocol_protocol" ><%= l(:setting_protocol)%></th> + <th class="protocol_command" ><%= l(:setting_checkout_command)%></th> + <th class="protocol_regex" ><%= l(:setting_checkout_url_regex) %></th> + <th class="protocol_regex_replacement"><%= l(:setting_checkout_url_regex_replacement) %></th> + <th class="protocol_access" ><%= l(:label_permissions) %></th> + <th class="protocol_append_path" ><%= l(:label_append_path) %></th> + <th class="protocol_is_default" ><%= l(:label_default) %></th> + <th class="protocol_delete" ></th> + </tr></thead> + <tbody id="settings_checkout_protocols_<%= scm %>"> + <% Setting.send("checkout_protocols_#{scm}").each_with_index do |protocol, index| %> + <%= render :partial => 'checkout_protocol', :locals => {:protocol => Checkout::Protocol.new(protocol), :scm => scm, :index => index, :classes => cycle('odd', 'even')} %> + <% end %> + </tbody> + </table> + <div style="text-align: right"><%= link_to_function l(:button_add_protocol), "protocolForms.get('#{scm}').add()", {:class => "icon icon-add"} %></div> +</div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_redmine_checkout.rhtml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,1 @@ +<%=l(:help_moved_settings, :link => link_to(l(:label_settings_location), {:controller => 'settings', :action => 'index', :tab => 'checkout'})) %>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/ZeroClipboard.as Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,81 @@ +package { + // Simple Set Clipboard System + // Author: Joseph Huckaby + + import flash.display.Stage; + import flash.display.Sprite; + import flash.display.LoaderInfo; + import flash.display.StageScaleMode; + import flash.events.*; + import flash.display.StageAlign; + import flash.display.StageScaleMode; + import flash.external.ExternalInterface; + import flash.system.Security; + import flash.utils.*; + import flash.system.System; + + public class ZeroClipboard extends Sprite { + + private var id:String = ''; + private var button:Sprite; + private var clipText:String = ''; + + public function ZeroClipboard() { + // constructor, setup event listeners and external interfaces + stage.scaleMode = StageScaleMode.EXACT_FIT; + flash.system.Security.allowDomain("*"); + + // import flashvars + var flashvars:Object = LoaderInfo( this.root.loaderInfo ).parameters; + id = flashvars.id; + + // invisible button covers entire stage + button = new Sprite(); + button.buttonMode = true; + button.useHandCursor = true; + button.graphics.beginFill(0xCCFF00); + button.graphics.drawRect(0, 0, Math.floor(flashvars.width), Math.floor(flashvars.height)); + button.alpha = 0.0; + addChild(button); + button.addEventListener(MouseEvent.CLICK, clickHandler); + + button.addEventListener(MouseEvent.MOUSE_OVER, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOver', null ); + } ); + button.addEventListener(MouseEvent.MOUSE_OUT, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOut', null ); + } ); + button.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseDown', null ); + } ); + button.addEventListener(MouseEvent.MOUSE_UP, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseUp', null ); + } ); + + // external functions + ExternalInterface.addCallback("setHandCursor", setHandCursor); + ExternalInterface.addCallback("setText", setText); + + // signal to the browser that we are ready + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'load', null ); + } + + public function setText(newText) { + // set the maximum number of files allowed + clipText = newText; + } + + public function setHandCursor(enabled:Boolean) { + // control whether the hand cursor is shown on rollover (true) + // or the default arrow cursor (false) + button.useHandCursor = enabled; + } + + private function clickHandler(event:Event):void { + // user click copies text to clipboard + // as of flash player 10, this MUST happen from an in-movie flash click event + System.setClipboard( clipText ); + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'complete', clipText ); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/button.svg Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,11 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <linearGradient id="gradient" x1="100%" y1="100%"> + <stop offset="0%" style="stop-color:#ddd; stop-opacity:1" /> + <stop offset="100%" style="stop-color:#f8f8f8; stop-opacity:1" /> + </linearGradient> + </defs> + <rect width="100%" height="100%" style="fill:url(#gradient)"/> +</svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/button_focus.svg Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,11 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <linearGradient id="gradient" x1="100%" y1="100%"> + <stop offset="0%" style="stop-color:#507AAA; stop-opacity:1" /> + <stop offset="100%" style="stop-color:#759fcf; stop-opacity:1" /> + </linearGradient> + </defs> + <rect width="100%" height="100%" style="fill:url(#gradient)"/> +</svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/button_selected.svg Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,11 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <linearGradient id="gradient" x1="100%" y1="100%"> + <stop offset="0%" style="stop-color:#aaa; stop-opacity:1" /> + <stop offset="100%" style="stop-color:#ccc; stop-opacity:1" /> + </linearGradient> + </defs> + <rect width="100%" height="100%" style="fill:url(#gradient)"/> +</svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/javascripts/ZeroClipboard.js Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,311 @@ +// Simple Set Clipboard System +// Author: Joseph Huckaby + +var ZeroClipboard = { + + version: "1.0.7", + clients: {}, // registered upload clients on page, indexed by id + moviePath: 'ZeroClipboard.swf', // URL to movie + nextId: 1, // ID of next movie + + $: function(thingy) { + // simple DOM lookup utility function + if (typeof(thingy) == 'string') thingy = document.getElementById(thingy); + if (!thingy.addClass) { + // extend element with a few useful methods + thingy.hide = function() { this.style.display = 'none'; }; + thingy.show = function() { this.style.display = ''; }; + thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; }; + thingy.removeClass = function(name) { + var classes = this.className.split(/\s+/); + var idx = -1; + for (var k = 0; k < classes.length; k++) { + if (classes[k] == name) { idx = k; k = classes.length; } + } + if (idx > -1) { + classes.splice( idx, 1 ); + this.className = classes.join(' '); + } + return this; + }; + thingy.hasClass = function(name) { + return !!this.className.match( new RegExp("\\s*" + name + "\\s*") ); + }; + } + return thingy; + }, + + setMoviePath: function(path) { + // set path to ZeroClipboard.swf + this.moviePath = path; + }, + + dispatch: function(id, eventName, args) { + // receive event from flash movie, send to client + var client = this.clients[id]; + if (client) { + client.receiveEvent(eventName, args); + } + }, + + register: function(id, client) { + // register new client to receive events + this.clients[id] = client; + }, + + getDOMObjectPosition: function(obj, stopObj) { + // get absolute coordinates for dom element + var info = { + left: 0, + top: 0, + width: obj.width ? obj.width : obj.offsetWidth, + height: obj.height ? obj.height : obj.offsetHeight + }; + + while (obj && (obj != stopObj)) { + info.left += obj.offsetLeft; + info.top += obj.offsetTop; + obj = obj.offsetParent; + } + + return info; + }, + + Client: function(elem) { + // constructor for new simple upload client + this.handlers = {}; + + // unique ID + this.id = ZeroClipboard.nextId++; + this.movieId = 'ZeroClipboardMovie_' + this.id; + + // register client with singleton to receive flash events + ZeroClipboard.register(this.id, this); + + // create movie + if (elem) this.glue(elem); + } +}; + +ZeroClipboard.Client.prototype = { + + id: 0, // unique ID for us + ready: false, // whether movie is ready to receive events or not + movie: null, // reference to movie object + clipText: '', // text to copy to clipboard + handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor + cssEffects: true, // enable CSS mouse effects on dom container + handlers: null, // user event handlers + + glue: function(elem, appendElem, stylesToAdd) { + // glue to DOM element + // elem can be ID or actual DOM element object + this.domElement = ZeroClipboard.$(elem); + + // float just above object, or zIndex 99 if dom element isn't set + var zIndex = 99; + if (this.domElement.style.zIndex) { + zIndex = parseInt(this.domElement.style.zIndex, 10) + 1; + } + + if (typeof(appendElem) == 'string') { + appendElem = ZeroClipboard.$(appendElem); + } + else if (typeof(appendElem) == 'undefined') { + appendElem = document.getElementsByTagName('body')[0]; + } + + // find X/Y position of domElement + var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem); + + // create floating DIV above element + this.div = document.createElement('div'); + var style = this.div.style; + style.position = 'absolute'; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + style.width = '' + box.width + 'px'; + style.height = '' + box.height + 'px'; + style.zIndex = zIndex; + + if (typeof(stylesToAdd) == 'object') { + for (addedStyle in stylesToAdd) { + style[addedStyle] = stylesToAdd[addedStyle]; + } + } + + // style.backgroundColor = '#f00'; // debug + + appendElem.appendChild(this.div); + + this.div.innerHTML = this.getHTML( box.width, box.height ); + }, + + getHTML: function(width, height) { + // return HTML for movie + var html = ''; + var flashvars = 'id=' + this.id + + '&width=' + width + + '&height=' + height; + + if (navigator.userAgent.match(/MSIE/)) { + // IE gets an OBJECT tag + var protocol = location.href.match(/^https/i) ? 'https://' : 'http://'; + html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>'; + } + else { + // all other browsers get an EMBED tag + html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />'; + } + return html; + }, + + hide: function() { + // temporarily hide floater offscreen + if (this.div) { + this.div.style.left = '-2000px'; + } + }, + + show: function() { + // show ourselves after a call to hide() + this.reposition(); + }, + + destroy: function() { + // destroy control and floater + if (this.domElement && this.div) { + this.hide(); + this.div.innerHTML = ''; + + var body = document.getElementsByTagName('body')[0]; + try { body.removeChild( this.div ); } catch(e) {;} + + this.domElement = null; + this.div = null; + } + }, + + reposition: function(elem) { + // reposition our floating div, optionally to new container + // warning: container CANNOT change size, only position + if (elem) { + this.domElement = ZeroClipboard.$(elem); + if (!this.domElement) this.hide(); + } + + if (this.domElement && this.div) { + var box = ZeroClipboard.getDOMObjectPosition(this.domElement); + var style = this.div.style; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + } + }, + + setText: function(newText) { + // set text to be copied to clipboard + this.clipText = newText; + if (this.ready) this.movie.setText(newText); + }, + + addEventListener: function(eventName, func) { + // add user event listener for event + // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + if (!this.handlers[eventName]) this.handlers[eventName] = []; + this.handlers[eventName].push(func); + }, + + setHandCursor: function(enabled) { + // enable hand cursor (true), or default arrow cursor (false) + this.handCursorEnabled = enabled; + if (this.ready) this.movie.setHandCursor(enabled); + }, + + setCSSEffects: function(enabled) { + // enable or disable CSS effects on DOM container + this.cssEffects = !!enabled; + }, + + receiveEvent: function(eventName, args) { + // receive event from flash + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + + // special behavior for certain events + switch (eventName) { + case 'load': + // movie claims it is ready, but in IE this isn't always the case... + // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function + this.movie = document.getElementById(this.movieId); + if (!this.movie) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 1 ); + return; + } + + // firefox on pc needs a "kick" in order to set these in certain cases + if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 100 ); + this.ready = true; + return; + } + + this.ready = true; + this.movie.setText( this.clipText ); + this.movie.setHandCursor( this.handCursorEnabled ); + break; + + case 'mouseover': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('hover'); + if (this.recoverActive) this.domElement.addClass('active'); + } + break; + + case 'mouseout': + if (this.domElement && this.cssEffects) { + this.recoverActive = false; + if (this.domElement.hasClass('active')) { + this.domElement.removeClass('active'); + this.recoverActive = true; + } + this.domElement.removeClass('hover'); + } + break; + + case 'mousedown': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('active'); + } + break; + + case 'mouseup': + if (this.domElement && this.cssEffects) { + this.domElement.removeClass('active'); + this.recoverActive = false; + } + break; + } // switch eventName + + if (this.handlers[eventName]) { + for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) { + var func = this.handlers[eventName][idx]; + + if (typeof(func) == 'function') { + // actual function reference + func(this, args); + } + else if ((typeof(func) == 'object') && (func.length == 2)) { + // PHP style object + method, i.e. [myObject, 'myMethod'] + func[0][ func[1] ](this, args); + } + else if (typeof(func) == 'string') { + // name of function + window[func](this, args); + } + } // foreach event handler defined + } // user defined handler for event + } + +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/javascripts/checkout.js Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,33 @@ +document.observe("dom:loaded", function() { + /* update the checkout URL if clicked on a protocol */ + $('checkout_protocols').select('a').each(function(e) { + e.observe('click', function(event) { + $('checkout_url').value = checkout_commands.get(this.id); + $('checkout_protocols').select('a').each(function(e) { + e.removeClassName("selected"); + }); + this.addClassName("selected") + + var value = checkout_access.get(this.id); + $('checkout_access').innerHTML = value; + + event.stop(); + }); + }); + /* select the text field contents if activated */ + Event.observe('checkout_url', 'click', function(event) { + this.activate(); + }); + + if (typeof('ZeroClipboard') != 'undefined') { + $('clipboard_container').show(); + clipboard = new ZeroClipboard.Client(); + clipboard.setHandCursor( true ); + clipboard.glue('clipboard_button', 'clipboard_container'); + + clipboard.addEventListener('mouseOver', function (client) { + clipboard.setText( $('checkout_url').value ); + }); + } +}); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/javascripts/subform.js Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,45 @@ +var Subform = Class.create({ + lineIndex: 1, + parentElement: "", + initialize: function(rawHTML, lineIndex, parentElement) { + this.rawHTML = rawHTML; + this.lineIndex = lineIndex; + this.parentElement = parentElement; + }, + + parsedHTML: function() { + return this.rawHTML.replace(/--INDEX--/g, this.lineIndex++); + }, + + add: function() { + var e = $(this.parentElement); + Element.insert(e, { bottom: this.parsedHTML()}); + Effect.toggle(e.childElements().last(), 'slide', {duration:0.2}); + recalculate_even_odd(e); + }, + + add_after: function(e) { + Element.insert(e, { after: this.parsedHTML()}); + Effect.toggle(e.next(), 'slide', {duration:0.2}); + recalculate_even_odd($(this.parentElement)); + }, + + add_on_top: function() { + var e = $(this.parentElement); + Element.insert(e, { top: this.parsedHTML()}); + Effect.toggle(e.childElements().first(), 'slide', {duration:0.2}); + recalculate_even_odd(e); + } +}); + +function recalculate_even_odd(element) { + $A(element.childElements()).inject( + 0, + function(acc, e) + { + e.removeClassName("even"); + e.removeClassName("odd"); + e.addClassName( (acc%2==0) ? "odd" : "even"); return ++acc; + } + ) +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/stylesheets/checkout.css Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,162 @@ +/* Uncomment the following line for nicer tables if you use the alternate theme (or derived). */ +/* @import url(checkout_alternate.css); */ + +table.checkout_protocol_table td { padding-right: 6px; vertical-align: middle; /* Double the border with of text input boxes */ } +table.checkout_protocol_table td.protocol_access { padding-right: 0; } +table.checkout_protocol_table td input[type=text], .checkout_protocol_table td select { width: 100%; } +table.checkout_protocol_table td.protocol_delete { width: 16px; } +table.checkout_protocol_table td.protocol_append_path, table.checkout_protocol_table td.protocol_is_default { text-align: center; } + +.icon-changeset { background-image: url(../../../images/changeset.png);} + +.repository-info { + background-color: #eee; + border: 1px solid #E4E4E4; + padding: 0 10px; + margin: 4px 0 10px; +} + +.bottomline { + border-bottom: 1px solid #ccc; +} + +#checkout_box { + margin: 10px 0; +} + +#checkout_protocols { + height: 23px; + float: left; + margin: 0; + padding: 0; +} + +#checkout_protocols li { + float: left; + list-style-type: none; + margin: 0; + padding: 0; +} + +#checkout_protocols li:first-child a { + border-left-width: 1px; + + /* Standard, Opera 10, IE 9 */ + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + /* Konquerer */ + -khtml-border-top-left-radius: 3px; + -khtml-border-bottom-left-radius: 3px; + /* Gecko (Firefox, ...) */ + -moz-border-radius: 3px 0 0 3px; + /* Webkit (Chrome, Safari, ...) */ + -webkit-border-top-left-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + /* IE <= 9 not supported */ +} + +#checkout_protocols li a, +#clipboard_button { + background-color: #eee; + background: url(../images/button.svg) 0 0 no-repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ + background: -khtml-gradient(linear, left top, left bottom, from(#f8f8f8), to(#ddd)); /* Konquerer */ + background: -moz-linear-gradient(top, #f8f8f8, #ddd); /* Gecko (Firefox, ...) */ + background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#ddd)); /* Webkit (Chrome, Safari, ...) */ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8f8f8', endColorstr='#dddddd'); /* IE 5.5 - 7 */ + -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8f8f8', endColorstr='#dddddd'); /* IE 8 */ + + border-color: #bbb; + border-style: solid; + border-width: 1px 1px 1px 0; + + color: #333; + display: block; + font-size: 11px; + font-weight: bold; + line-height: 21px; + margin: 0; + padding: 0 10px 0 11px; + text-decoration: none; + text-shadow: 1px 1px 0 #fff; + position: relative; /* to please IE */ +} + +#checkout_protocols li a:hover, +#checkout_protocols li a:focus { + background-color: #507AAA; + background: url(../images/button_focus.svg) 0 0 no-repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ + background: -khtml-gradient(linear, left top, left bottom, from(#759fcf), to(#507AAA)); /* Konquerer */ + background: -moz-linear-gradient(top, #759fcf, #507AAA); /* Gecko (Firefox, ...) */ + background: -webkit-gradient(linear, left top, left bottom, from(#759fcf), to(#507AAA)); /* Webkit (Chrome, Safari, ...) */ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#759fcf', endColorstr='#507AAA'); /* IE 5.5 - IE 7 */ + -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#759fcf', endColorstr='#507AAA'); /* IE 8 */ + + color: #fff; + text-shadow: -1px -1px 0 rgba(0,0,0,0.4); + border-top-color: #759fcf; + border-bottom-color: #507AAA; +} + +#checkout_protocols li a.selected, +#clipboard_button.active { + background-color: #bbb; + background: url(../images/button_selected.svg) 0 0 no-repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ + background: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#aaa)); /* Konquerer */ + background: -moz-linear-gradient(top, #ccc, #aaa); /* Gecko (Firefox, ...) */ + background: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#aaa)); /* Webkit (Chrome, Safari, ...) */ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#aaaaaa'); /* IE 5.5 - IE 7 */ + -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#aaaaaa'); /* IE 8 */ + + color: #000; + text-shadow: 1px 1px 0 rgba(255,255,255,0.4); + border-color: #bbb; +} + +#checkout_url { + border: 1px solid #bbb; + border-width: 1px 1px 1px 0; + background-color: #fff; + color: #000; + font-size: 11px; + height: 16px; + padding: 3px 5px 2px; + width: 400px; + font-family: Monaco,"DejaVu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace; + margin: 0 5px 0 0; + float: left; +} + +#checkout_box p { + color: #666; + line-height: 23px; + font-size: 11px; + margin: 0 0 0 5px; +} + +span#checkout_access { + font-weight: bold; +} + +#clipboard_container { + position: relative; + float: left; + margin-right: 5px; +} + +#clipboard_button { + height: 21px; + width: 23px; + padding: 0; + border-width: 1px; + text-align: center; + + border-radius: 5px; /* Standard, Opera 10, IE 9 */ + -khtml-border-radius: 3px; /* Konquerer */ + -moz-border-radius: 3px ; /* Gecko (Firefox, ...) */ + -webkit-border-radius: 3px; /* Webkit (Chrome, Safari, ...) */ + /* IE <= 9 not supported */ +} + +#clipboard_button img { + padding-top: 2px; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/stylesheets/checkout_alternate.css Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,2 @@ +table.checkout_protocol_table td { padding-right: 10px !important; /* Double the border with of text input boxes */ } +table.checkout_protocol_table td.protocol_access { padding-right: 2px !important; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/de.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +de: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Checkout-Informationen anzeigen" + setting_checkout_fixed_url: "Checkout-URL" + setting_checkout_url_regex: "Regulärer Ausdruck" + setting_checkout_url_regex_replacement: "Ersatztext" + setting_checkout_display_login: "Mitgliedsnamen anzeigen" + setting_checkout_command: "Checkout-Befehl" + setting_checkout_use_zero_clipboard: "Zwischenablagen-Helfer anzeigen" + + setting_checkout_overwrite_description: "Standard-Beschreibung überschreiben" + field_checkout_overwrite: "Überschreibe Standardeinstellung für Checkout-Protokolle" + field_checkout_display_command: "Checkout-Befehl anzeigen" + + label_protocol_plural: "Protokolle" + button_add_protocol: "Protokoll hinzufügen" + + label_access_type: 'Diese URL erlaubt Zugriff zum <span id="checkout_access">{{type}}</span>.' + label_access_read_only: 'Nur-Lesen' + label_access_read_write: "Lesen+Schreiben" + label_access_permission: "Abhängig von Benutzer-Rechten" + + label_append_path: "Pfad anhängen" + + label_display_login_none: "Mitgliedsnamen nicht anzeigen" + label_display_login_username: "Mitgliedsnamen anzeigen, aber kein Kennwort" + label_display_login_password: "Mitgliedsnamen und Kennwort anzeigen" + + label_copy_to_clipboard: "In die Zwischenablage kopieren" + + help_checkout_protocols: | + Die URLs in Protokollen werden aus der originalen URL erzeugt, auf die der + reguläre Ausdruck und der Ersatztext angewendet werden. Der Ersatztext + erlaubt Rückwärtsreferenzen zu geklammerten Audrücken mit der \1 Notation. + help_repository_checkout_protocols: | + Lassen Sie das Checkout-URL-Feld leer um die URL des Projektarchivs zu verwenden. + help_moved_settings: "Die Konfigurationsseite wurde nach {{link}} verschoben." + label_settings_location: "Administration -> Konfiguration -> Checkout" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/en-GB.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +en: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "Checkout URL" + setting_checkout_url_regex: "Regular expression" + setting_checkout_url_regex_replacement: "Replacement text" + setting_checkout_display_login: "Display Login" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Do not show login or password" + label_display_login_username: "Show login but no password" + label_display_login_password: "Show login and password" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/en.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +en: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "Checkout URL" + setting_checkout_url_regex: "Regular expression" + setting_checkout_url_regex_replacement: "Replacement text" + setting_checkout_display_login: "Display Login" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Do not show login or password" + label_display_login_username: "Show login but no password" + label_display_login_password: "Show login and password" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/es.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +es: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "URL de checkout" + setting_checkout_url_regex: "Expresion regular" + setting_checkout_url_regex_replacement: "Texto de remplazo" + setting_checkout_display_login: "Mostrar usuario" + setting_checkout_command: "Comando de checkout" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocolos" + button_add_protocol: "Crear Protocolo" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "No mostrar usuario o contraseña" + label_display_login_username: "Mostrar usuario pero no contraseña" + label_display_login_password: "Mostrar usuario y contraseña" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/fr.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +fr: + label_checkout: "Dépôt" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "URL du dépôt" + setting_checkout_url_regex: "Expression Régulière" + setting_checkout_url_regex_replacement: "Texte de substitution" + setting_checkout_display_login: "Affiche le login" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Affiche l'URL du dépôt" + + label_protocol_plural: "Protocoles" + button_add_protocol: "Créer un protocole" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Ne pas afficher le login ni le mot de passe" + label_display_login_username: "Afficher le login, pas le mot de passe" + label_display_login_password: "Afficher le login et le mot de passe" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/it.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,40 @@ +it: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Visualizza le informazioni sul checkout" + setting_checkout_fixed_url: "URL di checkout" + setting_checkout_url_regex: "Espressione regolare" + setting_checkout_url_regex_replacement: "Testo sostituito" + setting_checkout_display_login: "Login visualizzato" + setting_checkout_command: "Comando per il checkout" + setting_checkout_use_zero_clipboard: "Visualizza l'utility per la copia negli appunti" + + setting_checkout_overwrite_description: "Sovrascrivi la descrizione predefinita" + field_checkout_overwrite: "Sovrascrivi le impostazioni di checkout predefinite" + field_checkout_display_command: "Visualizza il comando per il checkout" + + label_protocol_plural: "Protocolli" + button_add_protocol: "Aggiungi Protocollo" + + label_access_type: 'Questo URL ha accesso <span id="checkout_access">{{type}}</span>.' + label_access_read_only: 'Sola-Lettura' + label_access_read_write: "Lettura+Scrittura" + label_access_permission: "Dipende dai permessi dell'utente" + + label_append_path: "Aggiungi percorso" + + label_display_login_none: "Non mostrare il login e password" + label_display_login_username: "Mostra il login senza password" + label_display_login_password: "Mostra il login e la password" + + label_copy_to_clipboard: "Copia negli appunti" + + help_checkout_protocols: | + Gli URL dei protocolli sono generati applicando le espressioni regolari + ed effettuando la sostituzione dell'URL originale con il testo specificato. + Il testo per la sostituzione può contenere riferimenti a più match usando + la notazione \1 \2... + help_repository_checkout_protocols: | + Lascia il campo URL di checkout bianco per usare l'URL definito nel repository. + help_moved_settings: "La pagina delle impostazioni è stata spostata in {{link}}." + label_settings_location: "Amministrazione -> Impostazioni -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/ja.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +ja: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "チェックアウト URL" + setting_checkout_url_regex: "Regular expression" + setting_checkout_url_regex_replacement: "Replacement text" + setting_checkout_display_login: "ログインの表示" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "ログインとパスワードを非表示" + label_display_login_username: "ログインのみ表示" + label_display_login_password: "ログインとパスワードを表示" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/ko.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,40 @@ +ko: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "체크 아웃 URL" + setting_checkout_url_regex: "정규식" + setting_checkout_url_regex_replacement: "대체 문자열" + setting_checkout_display_login: "로그인 표시" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "로그인과 비밀번호를 보여주지 않습니다." + label_display_login_username: "로그인은 보여주지만 비밀번호는 보여주지 않습니다." + label_display_login_password: "로그인과 비밀번호를 보여줍니다." + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/nl.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,40 @@ +nl: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Checkout-informatie tonen" + setting_checkout_fixed_url: "Checkout-URL" + setting_checkout_url_regex: "Reguliere expressie" + setting_checkout_url_regex_replacement: "Vervangingstekst" + setting_checkout_display_login: "Geef login weer" + setting_checkout_command: "Checkout-opdracht" + setting_checkout_use_zero_clipboard: "Klembord-hulp tonen" + + setting_checkout_overwrite_description: "Standaard omschrijving overschrijven" + field_checkout_overwrite: "Overschrijf standaard instellingen voor checkout-protocollen" + field_checkout_display_command: "Checkout-opdracht tonen" + + label_protocol_plural: "Protocollen" + button_add_protocol: "Protocol toevoegen" + + label_access_type: 'Deze URL heeft <span id="checkout_access">{{type}}</span> toegang.' + label_access_read_only: 'Alleen lezen' + label_access_read_write: "Lezen en schrijven" + label_access_permission: "Afhankelijk van gebruikersrechten" + + label_append_path: "Pad toevoegen" + + label_display_login_none: "Geen logingegevens tonen" + label_display_login_username: "Toon login zonder wachtwoord" + label_display_login_password: "Toon login en wachtwoord" + + label_copy_to_clipboard: "Naar klembord kopiëren" + + help_checkout_protocols: | + De URLs in protocollen worden samengesteld vanuit de originele URL, na + toepassing van de reguliere expressie en vervangingstekst. De vervangingstekst + ondersteunt referenties vanuit tussen haakjes geplaatste expressies + door middel van de \1 notatie. + help_repository_checkout_protocols: | + Laat het veld Checkout-URL leeg om de projectrepository te gebruiken. + help_moved_settings: "De instellingspagina is verplaatst naar {{link}}." + label_settings_location: "Administratie -> Instellingen -> Checkout" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/pl.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +pl: + label_checkout: "Pobieranie repozytorium" + + setting_checkout_display_checkout_info: "Pokaż informację o możliwości pobrania repozytorium" + setting_checkout_fixed_url: "Adres URL pobierania repozytorium" + setting_checkout_url_regex: "Wyrażenie regularne" + setting_checkout_url_regex_replacement: "Wynikowy adres URL" + setting_checkout_display_login: "Pokaż dane logowania" + setting_checkout_command: "Komenda pobrania repozytorium" + setting_checkout_use_zero_clipboard: "Pokaż pomocnika schowka" + + setting_checkout_overwrite_description: "Nadpisz domyślny opis" + field_checkout_overwrite: "Nadpisz domyślne ustawienia dla protokołów" + field_checkout_display_command: "Pokaż komendę pobrania repozytorium" + + label_protocol_plural: "Protokoły" + button_add_protocol: "Dodaj protokół" + + label_access_type: 'Ten adres URL ma dostęp <span id="checkout_access">{{type}}</span>.' + label_access_read_only: 'Tylko do odczytu' + label_access_read_write: "Odczyt+Zapis" + label_access_permission: "Zależne od uprawnień użytkownika" + + label_append_path: "Dołącz ścieżkę" + + label_display_login_none: "Nie pokazuj loginu ani hasła" + label_display_login_username: "Pokaż tylko login" + label_display_login_password: "Pokaż login i hasło" + + label_copy_to_clipboard: "Kopiuj do schowka" + + help_checkout_protocols: | + Wynikowe adresy URL w protokołach są generowane przez zamianę oryginalnego + adresu URL repozytorium na podstawie wyrażenia regularnego. Wynikowy adres + URL wspiera referencje do grup (tzw. back-references) używając notacji \1. + help_repository_checkout_protocols: | + Pozostaw adres URL pobierania repozytorium pusty aby uzyć adresu zdefiniowanego w ustawieniach projektu. + help_moved_settings: "Ustawienia zostały przeniesione do {{link}}." + label_settings_location: "Administracja -> Ustawienia -> Pobieranie repozytorium"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/ro.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,39 @@ +ro: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "URL-ul pentru checkout" + setting_checkout_url_regex: "Expresie regulata (regexp)" + setting_checkout_url_regex_replacement: "Text inlocuitor (regexp)" + setting_checkout_display_login: "Arata datele pentru autentificare" + setting_checkout_command: "Comanda de checkout" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Nu afisa username sau parola" + label_display_login_username: "Afiseaza username-ul, dar nu si parola" + label_display_login_password: "Afiseaza atat username-ul, cat si parola" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20091208210439_add_checkout_url_info.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,11 @@ +class AddCheckoutUrlInfo < ActiveRecord::Migration + def self.up + add_column :repositories, :checkout_url_type, :string, :default => 'none', :null => false + add_column :repositories, :checkout_url, :string, :default => '', :null => false + end + + def self.down + remove_column :repository, :checkout_url_type + remove_column :repository, :checkout_url + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20091220173312_add_display_login.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,9 @@ +class AddDisplayLogin < ActiveRecord::Migration + def self.up + add_column :repositories, :display_login, :string, :default => 'none', :null => false + end + + def self.down + remove_column :repositories, :display_login + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100118174556_add_render_link.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,9 @@ +class AddRenderLink < ActiveRecord::Migration + def self.up + add_column :repositories, :render_link, :boolean, :null => true + end + + def self.down + remove_column :repositories, :render_link + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100118235845_remove_defaults.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,14 @@ +class RemoveDefaults < ActiveRecord::Migration + def self.up + change_column :repositories, :checkout_url_type, :string, :default => nil, :null => true + change_column :repositories, :checkout_url, :string, :default => nil, :null => true + change_column :repositories, :display_login, :string, :default => nil, :null => true + end + + def self.down + change_column :repositories, :checkout_url_type, :string, :default => 'none', :null => false + change_column :repositories, :checkout_url, :string, :default => '', :null => false + change_column :repositories, :display_login, :string, :default => 'none', :null => false + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100118235909_add_overwrite_option.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,15 @@ +class AddOverwriteOption < ActiveRecord::Migration + def self.up + add_column :repositories, :checkout_url_overwrite, :boolean, :default => false, :null => false + + # existing repositories are set to overwrite the default settings + # This is to keep continuity of settings. + Repository.reset_column_information + Repository.update_all({:checkout_url_overwrite, true}) + end + + def self.down + remove_column :repositories, :checkout_url_overwrite + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100203202320_update_settings.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,36 @@ +class UpdateSettings < ActiveRecord::Migration + def self.up + settings = Setting.plugin_redmine_checkout + if settings['checkout_url_type'] == "overwritten" + settings['checkout_url_type'] = "generated" + end + + if settings.has_key? "checkout_url_regex" + settings['checkout_url_regex_default'] = settings.delete("checkout_url_regex") + end + + if settings.has_key? "checkout_url_regex_replacement" + settings['checkout_url_regex_replacement_default'] = settings.delete("checkout_url_regex_replacement") + end + + Setting.plugin_redmine_checkout = settings + end + + def self.down + settings = Setting.plugin_redmine_checkout + if settings['checkout_url_type'] == "generated" + settings['checkout_url_type'] = "overwritten" + end + + if settings.has_key? "checkout_url_regex_default" + settings['checkout_url_regex'] = settings.delete("checkout_url_regex_default") + end + + if settings.has_key? "checkout_url_regex_replacement_default" + settings['checkout_url_regex_replacement'] = settings.delete("checkout_url_regex_replacement_default") + end + + Setting.plugin_redmine_checkout = settings + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100426154202_rename_render_link_to_render_type.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,31 @@ +class RenameRenderLinkToRenderType < ActiveRecord::Migration + def self.up + render_link = Setting.plugin_redmine_checkout.delete 'render_link' + unless render_link.nil? + Setting.plugin_redmine_checkout['render_type'] = (render_link == 'true' ? 'link' : 'url') + Setting.plugin_redmine_checkout = Setting.plugin_redmine_checkout + end + + add_column :repositories, :render_type, :string, :default => 'url', :null => false + + Repository.update_all({:render_type => 'link'}, :render_link => true) + Repository.update_all({:render_type => 'url'}, ["render_link != ?", true]) + + remove_column :repositories, :render_link + end + + def self.down + render_type = Setting.plugin_redmine_checkout.delete 'render_type' + unless render_type.nil? + Setting.plugin_redmine_checkout['render_link'] = (render_type == 'link' ? 'true' : 'false') + Setting.plugin_redmine_checkout = Setting.plugin_redmine_checkout + end + + add_column :repositories, :render_link, :boolean, :null => true + + Repository.update_all({:render_link => true}, :render_type => 'link') + Repository.update_all({:render_link => false}, ["render_type != ?", 'link']) + + remove_column :repositories, :render_type + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100512135418_consolidate_repository_options.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,49 @@ +class ConsolidateRepositoryOptions < ActiveRecord::Migration + class Repository < ActiveRecord::Base + def self.inheritance_column + # disable single table inheritance + nil + end + + serialize :checkout_settings, Hash + end + + def self.up + add_column :repositories, :checkout_settings, :text + + Repository.all.each do |r| + r.checkout_settings = { + "checkout_url_type" => r.checkout_url_type, + "checkout_url" => r.checkout_url, + "display_login" => r.display_login, + "render_type" => r.render_type, + "checkout_url_overwrite" => r.checkout_url_overwrite + } + r.save! + end + remove_column :repositories, :checkout_url_type + remove_column :repositories, :checkout_url + remove_column :repositories, :display_login + remove_column :repositories, :render_type + remove_column :repositories, :checkout_url_overwrite + end + + def self.down + add_column :repositories, :checkout_url_type, :string, :default => nil, :null => true + add_column :repositories, :checkout_url, :string, :default => nil, :null => true + add_column :repositories, :display_login, :string, :default => nil, :null => true + add_column :repositories, :render_type, :string, :default => 'url', :null => false + add_column :repositories, :checkout_url_overwrite, :boolean, :default => false, :null => false + + Repository.all.each do |r| + r.checkout_url_type = r.checkout_settings["checkout_url_type"] + r.checkout_url = r.checkout_settings["checkout_url"] + r.display_login = r.checkout_settings["display_login"] + r.render_link = r.checkout_settings["render_link"] + r.checkout_url_overwrite = r.checkout_settings["checkout_url_overwrite"] + r.save! + end + + remove_column :repositories, :checkout_settings + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100609153630_apply_setting_changes.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,113 @@ +class ApplySettingChanges < ActiveRecord::Migration + class Repository < ActiveRecord::Base + def self.inheritance_column + # disable single table inheritance + nil + end + + def scm_name + self.type || 'Abstract' + end + + serialize :checkout_settings, Hash + end + + def self.up + default_commands = { + 'Bazaar' => 'bzr checkout', + 'Cvs' => 'cvs checkout', + 'Darcs' => 'darcs get', + 'Git' => 'git clone', + 'Mercurial' => 'hg clone', + 'Subversion' => 'svn checkout' + } + + ## First migrate the individual repositories + + Repository.all.each do |r| + allow_subtree_checkout = ['Cvs', 'Subversion'].include? r.scm_name + + protocol = case r.checkout_settings['checkout_url_type'] + when 'none', 'generated' + nil + when 'original', 'overwritten' + HashWithIndifferentAccess.new({ "0" => HashWithIndifferentAccess.new({ + :protocol => r.scm_name, + :command => Setting.plugin_redmine_checkout["checkout_cmd_#{r.scm_name}"] || default_commands[r.scm_name], + :regex => "", + :regex_replacement => "", + :fixed_url => (r.checkout_settings['checkout_url_type'] == 'original' ? (r.url || "") : r.checkout_settings["checkout_url"]), + :access => 'permission', + :append_path => (allow_subtree_checkout ? '1' : '0'), + :is_default => '1'}) + }) + end + + r.checkout_settings = Hash.new({ + 'checkout_protocols' => protocol, + 'checkout_description' => "The data contained in this repository can be downloaded to your computer using one of several clients. +Please see the documentation of your version control software client for more information. + +Please select the desired protocol below to get the URL.", + 'checkout_display_login' => (r.checkout_settings['display_login'] == 'none' ? '' : r.checkout_settings['display_login']), + 'checkout_overwrite' => (r.checkout_settings['checkout_url_overwrite'] == 'true') ? '1': '0', + 'checkout_display_command' => (r.checkout_settings["render_type"].to_s == 'cmd') ? '1' : '0' + }) + r.save! + end + + ## Then the global settings + + settings = HashWithIndifferentAccess.new({ + 'display_login' => Setting.plugin_redmine_checkout['display_login'], + 'use_zero_clipboard' => '1', + + 'display_checkout_info' => (Setting.plugin_redmine_checkout['checkout_url_type'] == 'none' ? '0' : '1'), + 'description_Abstract' => <<-EOF +The data contained in this repository can be downloaded to your computer using one of several clients. +Please see the documentation of your version control software client for more information. + +Please select the desired protocol below to get the URL. +EOF + }) + + default_commands.keys.each do |scm| + settings["description_#{scm}"] = '' + settings["overwrite_description_#{scm}"] = '0' + + display_command = (Setting.plugin_redmine_checkout["render_type"].to_s == 'cmd') ? '1' : '0' + settings["display_command_#{scm}"] = display_command + + case Setting.plugin_redmine_checkout['checkout_url_type'] + when 'generated', 'none': + regex = Setting.plugin_redmine_checkout["checkout_url_regex_#{scm}"] + replacement = Setting.plugin_redmine_checkout["checkout_url_regex_replacement_#{scm}"] + when 'original': + regex = '' + replacement = '' + end + + settings["protocols_#{scm}"] = HashWithIndifferentAccess.new({ + # access can be one of + # read+write => this protocol always allows read/write access + # read-only => this protocol always allows read access only + # permission => Access depends on redmine permissions + '0' => HashWithIndifferentAccess.new({ + :protocol => scm, + :command => Setting.plugin_redmine_checkout["checkout_cmd_#{scm}"] || default_commands[scm], + :regex => regex, + :regex_replacement => replacement, + :fixed_url => '', + :access => 'permission', + :append_path => (['Cvs', 'Subversion'].include?(scm) ? '1' : '0'), + :is_default => '1' + }) + }) + end + Setting.plugin_redmine_checkout = settings + end + + def self.down + raise ActiveRecord::IrreversibleMigration.new "Sorry, there is no down migration yet. If you really need one, please create an issue on http://dev.holgerjust.de/projects/redmine-checkout" + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100808185600_change_protocol_storage_from_hash_to_array.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,58 @@ +class ChangeProtocolStorageFromHashToArray < ActiveRecord::Migration + class Repository < ActiveRecord::Base + def self.inheritance_column + # disable single table inheritance + nil + end + + def scm_name + self.type || 'Abstract' + end + + serialize :checkout_settings, Hash + end + + def self.up + ## First migrate the individual repositories + Repository.all.each do |r| + next unless r.checkout_settings + next unless r.checkout_settings['checkout_protocols'].is_a? Hash + r.checkout_settings['checkout_protocols'] = r.checkout_settings['checkout_protocols'].sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} + r.save! + end + + ## Then the global settings + settings = Setting.plugin_redmine_checkout + settings.keys.grep(/^protocols_/).each do |protocols| + next unless settings[protocols].is_a? Hash + settings[protocols] = settings[protocols].sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} + end + Setting.plugin_redmine_checkout = settings + end + + def self.down + ## First migrate the individual repositories + Repository.all.each do |r| + next unless r.checkout_settings['checkout_protocols'].is_a? Hash + r.checkout_settings['checkout_protocols'] = r.checkout_settings['checkout_protocols'].inject(HashWithIndifferentAccess.new) do |result, p| + result[result.length.to_s] = p + end + r.save! + end + + ## Then the global settings + settings = Setting.plugin_redmine_checkout + settings.keys.grep(/^protocols_/).each do |protocols| + next unless r.checkout_settings['checkout_protocols'].is_a? Hash + settings[protocols] = settings[protocols].inject(HashWithIndifferentAccess.new) do |result, p| + result[result.length.to_s] = p + end + end + Setting.plugin_redmine_checkout = settings + + + + + raise ActiveRecord::IrreversibleMigration.new "Sorry, there is no down migration yet. If you really need one, please create an issue on http://dev.holgerjust.de/projects/redmine-checkout" + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/doc/COPYING Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,22 @@ +Copyright (c) 2009 Holger Just + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/init.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,102 @@ +require 'redmine' + +require 'dispatcher' +Dispatcher.to_prepare do + # Patches + require_dependency 'checkout/settings_controller_patch' + + require_dependency 'checkout/repositories_helper_patch' + require_dependency 'checkout/repository_patch' + + require_dependency 'checkout/settings_helper_patch' + require_dependency 'checkout/setting_patch' +end + +# Hooks +require 'checkout/repository_hooks' + +Redmine::Plugin.register :redmine_checkout do + name 'Redmine Checkout plugin' + url 'http://dev.holgerjust.de/projects/redmine-checkout' + author 'Holger Just' + author_url 'http://meine-er.de' + description 'Add links to the actual repository to the repository view.' + version '0.5' + + requires_redmine :version_or_higher => '0.9' + + settings_defaults = HashWithIndifferentAccess.new({ + 'display_login' => nil, + 'use_zero_clipboard' => '1', + + 'display_checkout_info' => '1', + 'description_Abstract' => <<-EOF +The data contained in this repository can be downloaded to your computer using one of several clients. +Please see the documentation of your version control software client for more information. + +Please select the desired protocol below to get the URL. +EOF + }) + + # this is needed for setting the defaults + require 'checkout/repository_patch' + + CheckoutHelper.supported_scm.each do |scm| + klazz = "Repository::#{scm}".constantize + + settings_defaults["description_#{scm}"] = '' + settings_defaults["overwrite_description_#{scm}"] = '0' + settings_defaults["display_command_#{scm}"] = '0' + + # access can be one of + # read+write => this protocol always allows read/write access + # read-only => this protocol always allows read access only + # permission => Access depends on redmine permissions + settings_defaults["protocols_#{scm}"] = [HashWithIndifferentAccess.new({ + :protocol => scm, + :command => klazz.checkout_default_command, + :regex => '', + :regex_replacement => '', + :fixed_url => '', + :access => 'permission', + :append_path => (klazz.allow_subtree_checkout? ? '1' : '0'), + :is_default => '1' + })] + end + + settings :default => settings_defaults, :partial => 'settings/redmine_checkout' + + Redmine::WikiFormatting::Macros.register do + desc <<-EOF +Creates a checkout link to the actual repository. Example: + + use the default checkout protocol !{{repository}} + or use a specific protocol !{{repository(SVN)}} + or use the checkout protocol of a specific specific project: !{{repository(projectname:SVN)}}" +EOF + + macro :repository do |obj, args| + proto = args.first + if proto.to_s =~ %r{^([^\:]+)\:(.*)$} + project_identifier, proto = $1, $2 + project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier) + else + project = @project + end + + if project && project.repository + protocols = project.repository.checkout_protocols.select{|p| p.access_rw(User.current)} + + if proto.present? + proto_obj = protocols.find{|p| p.protocol.downcase == proto.downcase} + else + proto_obj = protocols.find(&:default?) || protocols.first + end + end + raise "Checkout protocol #{proto} not found" unless proto_obj + + cmd = (project.repository.checkout_display_command? && proto_obj.command.present?) ? proto_obj.command.strip + " " : "" + cmd + link_to(proto_obj.url, proto_obj.url) + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/protocol.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,114 @@ +module Checkout + class <<self + def awesome? + # Yes, this plugin is awesome! + true + end + end + + class Protocol + attr_accessor :protocol, :regex, :regex_replacement, :access, :repository + attr_writer :default, :command, :fixed_url, :append_path + + + def initialize(args={}) + args = args.dup + + @protocol = args.delete :protocol + @command = args.delete :command # optional, if not set the default from the repo is used + + # either a fixed url + @fixed_url = args.delete :fixed_url + + # or a regex + @regex = args.delete :regex + @regex_replacement = args.delete :regex_replacement + + @access = args.delete :access + @append_path = args.delete :append_path + @default = args.delete :is_default + + @repository = args.delete :repository + end + + def full_command(path = "") + cmd = "" + if repository.checkout_display_command? + cmd = self.command.present? ? self.command.strip + " " : "" + end + cmd + URI.escape(self.url(path)) + end + + def default? + @default.to_i > 0 + end + + def command + @command || self.repository && self.repository.checkout_default_command || "" + end + + def append_path? + @append_path.to_i > 0 + end + + def access_rw(user) + # reduces the three available access levels 'read+write', 'read-only' and 'permission' + # to 'read+write' and 'read-only' and nil (not allowed) + + @access_rw ||= {} + return @access_rw[user] if @access_rw.key? user + @access_rw[user] = case access + when 'permission' + case + when user.allowed_to?(:commit_access, repository.project) && user.allowed_to?(:browse_repository, repository.project) + 'read+write' + when user.allowed_to?(:browse_repository, repository.project) + 'read-only' + else + nil + end + else + @access + end + end + + def access_label(user) + case access_rw(user) + when 'read+write': :label_access_read_write + when 'read-only': :label_access_read_only + end + end + + def fixed_url + @fixed_url.present? ? @fixed_url : begin + if (regex.blank? || regex_replacement.blank?) + repository.url + else + repository.url.gsub(Regexp.new(regex), regex_replacement) + end + end + rescue RegexpError + repository.url || "" + end + + def url(path = "") + return "" unless repository + + url = fixed_url.sub(/\/+$/, "") + if repository.allow_subtree_checkout? && self.append_path? && path.present? + url = "#{url}/#{path}" + end + + if repository.checkout_display_login? + begin + uri = URI.parse url + (uri.user = repository.login) if repository.login + (uri.password = repository.password) if (repository.checkout_display_login == 'password' && repository.login && repository.password) + url = uri.to_s + rescue URI::InvalidURIError + end + end + url + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/repositories_helper_patch.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,34 @@ +require_dependency 'repositories_helper' + +module Checkout + module RepositoriesHelperPatch + def self.included(base) # :nodoc: + base.send(:include, InstanceMethods) + + base.class_eval do + alias_method_chain :repository_field_tags, :checkout + alias_method_chain :scm_select_tag, :javascript + end + end + + module InstanceMethods + def repository_field_tags_with_checkout(form, repository) + tags = repository_field_tags_without_checkout(form, repository) || "" + return tags if repository.class.name == "Repository" + + tags + @controller.send(:render_to_string, :partial => 'projects/settings/repository_checkout', :locals => {:form => form, :repository => repository, :scm => repository.scm_name}) + end + + def scm_select_tag_with_javascript(*args) + content_for :header_tags do + javascript_include_tag('subform', :plugin => 'redmine_checkout') + + stylesheet_link_tag('checkout', :plugin => 'redmine_checkout') + end + scm_select_tag_without_javascript(*args) + end + end + end +end + +RepositoriesHelper.send(:include, Checkout::RepositoriesHelperPatch) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/repository_hooks.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,34 @@ +module Checkout + class RepositoryHooks < Redmine::Hook::ViewListener + # Renders the checkout URL + # + # Context: + # * :project => Current project + # * :repository => Current Repository + # + def view_repositories_show_contextual(context={}) + if context[:repository].present? && Setting.checkout_display_checkout_info? + protocols = context[:repository].checkout_protocols.select do |p| + p.access_rw(User.current) + end + + path = context[:controller].instance_variable_get("@path") + if path && context[:controller].instance_variable_get("@entry") + # a single file is showing, so we return only the directory + path = File.dirname(path) + end + + default = protocols.find(&:default?) || protocols.first + + context.merge!({ + :protocols => protocols, + :default_protocol => default, + :checkout_path => path + }) + + options = {:partial => "redmine_checkout_hooks/view_repositories_show_contextual"} + context[:controller].send(:render_to_string, {:locals => context}.merge(options)) + end + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/repository_patch.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,186 @@ +require_dependency 'repository' +require_dependency 'checkout_helper' + +module Checkout + module RepositoryPatch + def self.included(base) # :nodoc: + base.extend(ClassMethods) + base.send(:include, InstanceMethods) + + base.class_eval do + unloadable + serialize :checkout_settings, Hash + end + end + + module ClassMethods + def allow_subtree_checkout? + # default implementation + false + end + + def checkout_default_command + # default implementation + "" + end + end + + module InstanceMethods + def after_initialize + self.checkout_settings ||= {} + end + + def checkout_overwrite=(value) + checkout_settings['checkout_overwrite'] = value + end + + def checkout_overwrite + (checkout_settings['checkout_overwrite'].to_i > 0) ? '1' : '0' + end + + def checkout_overwrite? + self.scm_name != 'Abstract' && checkout_overwrite.to_i > 0 + end + + def checkout_description=(value) + checkout_settings['checkout_description'] = value + end + + def checkout_description + if checkout_overwrite? + checkout_settings['checkout_description'] + else + if CheckoutHelper.supported_scm.include?(scm_name) && Setting.send("checkout_overwrite_description_#{scm_name}?") + Setting.send("checkout_description_#{scm_name}") + else + Setting.send("checkout_description_Abstract") + end + end + end + + def checkout_protocols + @checkout_protocols ||= begin + if CheckoutHelper.supported_scm.include? scm_name + if checkout_overwrite? + protocols = checkout_settings['checkout_protocols'] || [] + else + protocols = Setting.send("checkout_protocols_#{scm_name}") || [] + end + else + protocols = [] + end + + protocols.collect do |p| + Checkout::Protocol.new p.merge({:repository => self}) + end + end + end + + def checkout_protocols=(value) + # value is an Array or a Hash + if value.is_a? Hash + value = value.dup.delete_if {|id, protocol| id.to_i < 0 } + value = value.sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} + end + + checkout_settings['checkout_protocols'] = value + end + + def checkout_display_login + if checkout_overwrite? && self.scm_name == "Subversion" + result = checkout_settings['checkout_display_login'] + else + result = Setting.checkout_display_login + end + (result.to_i > 0) ? '1' : '0' + end + + def checkout_display_login? + checkout_display_login.to_i > 0 + end + + def checkout_display_login=(value) + value = nil unless self.scm_name == "Subversion" + checkout_settings['checkout_display_login'] = value + end + + def checkout_display_command? + checkout_display_command.to_i > 0 + end + + def checkout_display_command=(value) + checkout_settings['checkout_display_command'] = value + end + + def checkout_display_command + if checkout_overwrite? + checkout_settings['checkout_display_command'] + else + Setting.send("checkout_display_command_#{scm_name}") + end + end + + def allow_subtree_checkout? + self.class.allow_subtree_checkout? + end + + def checkout_default_command + self.class.checkout_default_command + end + end + end +end + +Repository.send(:include, Checkout::RepositoryPatch) + +subtree_checkout_repos = ["Subversion", "Cvs"] +commands = { + 'Bazaar' => 'bzr checkout', + 'Cvs' => 'cvs checkout', + 'Darcs' => 'darcs get', + 'Git' => 'git clone', + 'Mercurial' => 'hg clone', + 'Subversion' => 'svn checkout' +} + +CheckoutHelper.supported_scm.each do |scm| + require_dependency "repository/#{scm.underscore}" + cls = Repository.const_get(scm) + + allow_subtree_checkout = "" + if subtree_checkout_repos.include? scm + allow_subtree_checkout = <<-EOS + def allow_subtree_checkout? + true + end + EOS + end + + checkout_command = "" + if commands[scm] + checkout_command = <<-EOS + def checkout_default_command + '#{commands[scm]}' + end + EOS + end + + class_mod = Module.new + class_mod.module_eval(<<-EOF + def self.included(base) + base.extend ChildClassMethods + + base.class_eval do + unloadable + serialize :checkout_settings, Hash + end + end + + module ChildClassMethods + #{allow_subtree_checkout} + #{checkout_command} + end + EOF + ) + cls.send(:include, class_mod) +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/setting_patch.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,75 @@ +require_dependency 'setting' + +module Checkout + module SettingPatch + def self.included(base) # :nodoc: + base.extend(ClassMethods) + + base.class_eval do + unloadable + + # Defines getter and setter for each setting + # Then setting values can be read using: Setting.some_setting_name + # or set using Setting.some_setting_name = "some value" + Redmine::Plugin.find(:redmine_checkout).settings[:default].keys.each do |name| + if name.start_with?('protocols_') + default = "[]" + else + default = <<-END_SRC + begin + default = Setting.available_settings['plugin_redmine_checkout']['default']['#{name}'] + # perform a deep copy of the default + Marshal::load(Marshal::dump(default)) + end + END_SRC + end + + src = <<-END_SRC + def self.checkout_#{name} + self.plugin_redmine_checkout[:#{name}] || #{default} + end + + def self.checkout_#{name}? + self.checkout_#{name}.to_i > 0 + end + + def self.checkout_#{name}=(value) + setting = Setting.plugin_redmine_checkout + setting[:#{name}] = value + Setting.plugin_redmine_checkout = setting + end + END_SRC + class_eval src, __FILE__, __LINE__ + end + + class <<self + alias_method :store_without_checkout, :[]= + alias_method :[]=, :store_with_checkout + + alias_method :retrieve_without_checkout, :[] + alias_method :[], :retrieve_with_checkout + end + end + end + + module ClassMethods + def store_with_checkout(name, value) + if name.to_s.starts_with? "checkout_" + self.send("#{name}=", value) + else + store_without_checkout(name, value) + end + end + + def retrieve_with_checkout(name) + if name.to_s.starts_with? "checkout_" + self.send("#{name}") + else + retrieve_without_checkout(name) + end + end + end + end +end + +Setting.send(:include, Checkout::SettingPatch) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/settings_controller_patch.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,44 @@ +require_dependency 'settings_controller' + +module Checkout + module SettingsControllerPatch + def self.included(base) # :nodoc: + base.send(:include, InstanceMethods) + + base.class_eval do + unloadable + + alias_method_chain :edit, :checkout + end + end + + module InstanceMethods + def edit_with_checkout + if request.post? && params['tab'] == 'checkout' + if params[:settings] && params[:settings].is_a?(Hash) + settings = HashWithIndifferentAccess.new + (params[:settings] || {}).each do |name, value| + if name = name.to_s.slice(/checkout_(.+)/, 1) + case value + when Array + # remove blank values in array settings + value.delete_if {|v| v.blank? } + when Hash + # change protocols hash to array. + value = value.sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} if name.start_with? "protocols_" + end + settings[name.to_sym] = value + end + end + + Setting.plugin_redmine_checkout = settings + params[:settings] = {} + end + end + edit_without_checkout + end + end + end +end + +SettingsController.send(:include, Checkout::SettingsControllerPatch)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/settings_helper_patch.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,23 @@ +require_dependency 'settings_helper' + +module Checkout + module SettingsHelperPatch + def self.included(base) # :nodoc: + base.send(:include, InstanceMethods) + + base.class_eval do + alias_method_chain :administration_settings_tabs, :checkout + end + end + + module InstanceMethods + def administration_settings_tabs_with_checkout + tabs = administration_settings_tabs_without_checkout + tabs << {:name => 'checkout', :partial => 'settings/checkout', :label => :label_checkout} + end + end + end +end + +SettingsHelper.send(:include, Checkout::SettingsHelperPatch) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout_helper.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,7 @@ +module CheckoutHelper + class <<self + def supported_scm + Object.const_defined?("REDMINE_SUPPORTED_SCM") ? REDMINE_SUPPORTED_SCM : Redmine::Scm::Base.all + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/tasks/set_default.rake Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,10 @@ +namespace :redmine do + namespace :plugins do + namespace :redmine_checkout do + desc "Sets all repositories to inherit the default setting for the checkout URL." + task :set_default => :environment do + Repository.all.each{|r| r.update_attributes(:checkout_overwrite => "0")} + end + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/tasks/spec.rake Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,14 @@ +begin + require "spec/rake/spectask" + namespace :spec do + namespace :plugins do + desc "Runs the examples for redmine_checkout" + Spec::Rake::SpecTask.new(:redmine_checkout) do |t| + t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""] + t.spec_files = FileList['vendor/plugins/redmine_checkout/spec/**/*_spec.rb'] + end + end + end + task :spec => "spec:plugins:redmine_checkout" +rescue LoadError +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/controllers/repositories_controller_spec.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,48 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe RepositoriesController do + fixtures :settings, :repositories, :projects, :roles, :users, :enabled_modules + integrate_views + + before(:each) do + Setting.default_language = 'en' + User.current = nil + end + + def get_repo + get :show, :id => 1 + end + + it "should display the protocol selector" do + get_repo + response.should be_success + response.should render_template('show') + + response.should have_tag('ul#checkout_protocols') do + with_tag('a[id=?][href=?]', 'checkout_protocol_subversion', "file:///#{RAILS_ROOT.gsub(%r{config\/\.\.}, '')}/tmp/test/subversion_repository") + with_tag('a[id=?][href=?]', 'checkout_protocol_svn+ssh', 'svn+ssh://subversion_repository@svn.foo.bar/svn') + end + end + + it "should display the description" do + get_repo + response.should be_success + response.should render_template('show') + + response.should have_tag('div.repository-info', /Please select the desired protocol below to get the URL/) + end + + it 'should respect the use zero clipboard option' do + Setting.checkout_use_zero_clipboard = '1' + get_repo + response.should be_success + response.should render_template('show') + response.should have_tag('script[src*=?]', 'ZeroClipboard') + + Setting.checkout_use_zero_clipboard = '0' + get_repo + response.should be_success + response.should render_template('show') + response.should_not have_tag('script[src*=]', 'ZeroClipboard') + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/enabled_modules.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,5 @@ +--- +enabled_modules_001: + name: repository + project_id: 1 + id: 1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/projects.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,13 @@ +--- +projects_001: + created_on: 2006-07-19 19:13:59 +02:00 + name: eCookbook + updated_on: 2006-07-19 22:53:01 +02:00 + id: 1 + description: Recipes management application + homepage: http://ecookbook.somenet.foo/ + is_public: true + identifier: ecookbook + parent_id: + lft: 1 + rgt: 10
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/repositories.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,9 @@ +--- +svn: + project_id: 1 + url: file:///<%= RAILS_ROOT.gsub(%r{config\/\.\.}, '') %>/tmp/test/subversion_repository + id: 1 + root_url: file:///<%= RAILS_ROOT.gsub(%r{config\/\.\.}, '') %>/tmp/test/subversion_repository + password: "" + login: "" + type: Subversion
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/roles.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,187 @@ +--- +roles_001: + name: Manager + id: 1 + builtin: 0 + permissions: | + --- + - :add_project + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :manage_subtasks + - :add_issue_notes + - :move_issues + - :delete_issues + - :view_issue_watchers + - :add_issue_watchers + - :delete_issue_watchers + - :manage_public_queries + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :edit_time_entries + - :delete_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :export_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :delete_wiki_pages_attachments + - :protect_wiki_pages + - :delete_wiki_pages + - :rename_wiki_pages + - :add_messages + - :edit_messages + - :delete_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :manage_repository + - :view_changesets + - :manage_project_activities + + position: 1 +roles_002: + name: Developer + id: 2 + builtin: 0 + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :manage_subtasks + - :add_issue_notes + - :move_issues + - :delete_issues + - :view_issue_watchers + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :edit_own_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :protect_wiki_pages + - :delete_wiki_pages + - :add_messages + - :edit_own_messages + - :delete_own_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 2 +roles_003: + name: Reporter + id: 3 + builtin: 0 + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :move_issues + - :view_issue_watchers + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :delete_wiki_pages + - :add_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 3 +roles_004: + name: Non member + id: 4 + builtin: 1 + permissions: | + --- + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :move_issues + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :add_messages + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 4 +roles_005: + name: Anonymous + id: 5 + builtin: 2 + permissions: | + --- + - :view_issues + - :add_issue_notes + - :view_gantt + - :view_calendar + - :view_time_entries + - :view_documents + - :view_wiki_pages + - :view_wiki_edits + - :view_files + - :browse_repository + - :view_changesets + + position: 5 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/settings.yml Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,115 @@ +--- + settings: + name: plugin_redmine_checkout + value: | + --- !map:HashWithIndifferentAccess + display_checkout_info: "1" + description_Abstract: | + The data contained in this repository can be downloaded to your computer using one of several clients. + Please see the documentation of your version control software client for more information. + + Please select the desired protocol below to get the URL. + display_command_Bazaar: '1' + use_zero_clipboard: "1" + + overwrite_description_Bazaar: "0" + description_Bazaar: "" + display_command_Bazaar: '1' + protocols_Bazaar: + "0": !map:HashWithIndifferentAccess + command: "bzr checkout" + regex: "" + regex_replacement: "" + read_write: readwrite + append_path: "0" + is_default: "1" + protocol: Bazaar + overwrite_description_Cvs: "0" + description_Cvs: "" + display_command_Cvs: '1' + protocols_Cvs: + "0": !map:HashWithIndifferentAccess + command: "cvs checkout" + regex: "" + regex_replacement: "" + read_write: readwrite + append_path: "0" + is_default: "1" + protocol: Cvs + overwrite_description_Darcs: "0" + description_Darcs: "" + display_command_Darcs: '1' + protocols_Darcs: + "0": !map:HashWithIndifferentAccess + command: "darcs get" + regex: "" + regex_replacement: "" + read_write: readwrite + append_path: "0" + is_default: "1" + protocol: Darcs + overwrite_description_Filesystem: "0" + description_Filesystem: "" + display_command_Filesystem: '1' + protocols_Filesystem: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "" + regex: "" + append_path: "0" + is_default: "1" + protocol: Filesystem + access: read+write + regex_replacement: "" + overwrite_description_Git: "0" + description_Git: "" + display_command_Git: '1' + protocols_Git: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "git clone" + regex: "" + append_path: "0" + is_default: "1" + protocol: Git + access: read+write + regex_replacement: "" + overwrite_description_Mercurial: "0" + description_Mercurial: "" + display_command_Mercurial: '1' + protocols_Mercurial: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "hg clone" + regex: "" + append_path: "0" + is_default: "1" + protocol: Mercurial + access: read+write + regex_replacement: "" + display_login: username + overwrite_description_Subversion: "0" + description_Subversion: "" + display_command_Subversion: '1' + protocols_Subversion: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "svn checkout" + regex: foo + append_path: "1" + is_default: "1" + protocol: Subversion + access: permission + regex_replacement: bar + "1": !map:HashWithIndifferentAccess + command: "svn co" + regex: "^.*?([^/]+)/?$" + append_path: "1" + is_default: "0" + protocol: SVN+SSH + access: read-only + regex_replacement: svn+ssh://\1@svn.foo.bar/svn + "2": !map:HashWithIndifferentAccess + command: "svn checkout" + append_path: "0" + is_default: "0" + regex: "" + protocol: Root + access: read+write + regex_replacement: ""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/macros/macro_spec.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,55 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe "Macros" do + fixtures :settings, :repositories, :projects, :enabled_modules + + include ERB::Util + include ApplicationHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + + before(:each) do + Setting.checkout_display_command_Subversion = '0' + + @project = projects :projects_001 + end + + + it "should display default checkout url" do + text = "{{repository}}" + + url = "file:///#{RAILS_ROOT.gsub(%r{config\/\.\.}, '')}/tmp/test/subversion_repository" + textilizable(text).should eql "<p><a href=\"#{url}\">#{url}</a></p>" + end + + it "should display forced checkout url" do + text = "{{repository(svn+ssh)}}" + + url = 'svn+ssh://subversion_repository@svn.foo.bar/svn' + textilizable(text).should eql "<p><a href=\"#{url}\">#{url}</a></p>" + end + + it "should fail without set project" do + @project = nil + + text = "{{repository(svn+ssh)}}" + textilizable(text).should eql "<p><div class=\"flash error\">Error executing the <strong>repository</strong> macro (Checkout protocol svn+ssh not found)</div></p>" + end + + it "should display checkout url from stated project" do + @project = nil + text = "{{repository(ecookbook:svn+ssh)}}" + + url = 'svn+ssh://subversion_repository@svn.foo.bar/svn' + textilizable(text).should eql "<p><a href=\"#{url}\">#{url}</a></p>" + end + + it "should display command" do + Setting.checkout_display_command_Subversion = '1' + + text = "{{repository(svn+ssh)}}" + url = 'svn+ssh://subversion_repository@svn.foo.bar/svn' + textilizable(text).should eql "<p>svn co <a href=\"#{url}\">#{url}</a></p>" + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/models/protocol_spec.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,36 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Checkout::Protocol do + fixtures :settings, :repositories, :projects, :enabled_modules + + before(:each) do + @admin = User.new + @admin.admin = true + @user = User.new + + @repo = repositories :svn + @repo.url = "http://example.com/svn/testrepo" + end + + it "should use regexes for generated URL" do + protocol = @repo.checkout_protocols.find{|r| r.protocol == "SVN+SSH"} + protocol.url.should eql "svn+ssh://testrepo@svn.foo.bar/svn" + end + + it "should resolve access properties" do + protocol = @repo.checkout_protocols.find{|r| r.protocol == "Subversion"} + protocol.access.should eql "permission" + protocol.access_rw(@admin).should eql "read+write" + + User.current = @user + protocol.access_rw(@user).should eql "read-only" + end + + it "should display the checkout command" do + subversion = @repo.checkout_protocols.find{|r| r.protocol == "Subversion"} + svn_ssh = @repo.checkout_protocols.find{|r| r.protocol == "SVN+SSH"} + + subversion.command.should eql "svn checkout" + svn_ssh.command.should eql "svn co" + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/models/repository_spec.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,49 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Repository do + fixtures :settings, :repositories + + describe "initialize" do + before(:each) do + @repo = Repository.new() + end + + it "should properly set default values" do + @repo.checkout_overwrite?.should be_false + @repo.checkout_description.should match /Please select the desired protocol below to get the URL/ + @repo.checkout_display_login?.should be_false # no subversion repo + @repo.allow_subtree_checkout?.should be_false + @repo.checkout_protocols.should eql [] + end + end + + describe "subtree checkout" do + before(:each) do + @svn = Repository::Subversion.new + @git = Repository::Git.new + end + it "should be allowed on subversion" do + @svn.allow_subtree_checkout?.should eql true + end + it "should only be possible if checked" do + + end + + it "should be forbidden on git" do + @git.allow_subtree_checkout?.should eql false + end + end + + describe "extensions" do + before(:each) do + @repo = Repository::Subversion.new + end + + it "should provide protocols" do + protocols = @repo.checkout_protocols + protocols[0].protocol.should eql "Subversion" + protocols[1].protocol.should eql "SVN+SSH" + protocols[2].protocol.should eql "Root" + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/models/setting_spec.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,14 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Setting do + fixtures :settings + + before(:each) do + Setting.default_language = 'en' + end + + it "should recognize checkout methods" do + Setting.checkout_display_checkout_info.should eql Setting.plugin_redmine_checkout['display_checkout_info'] + Setting.checkout_display_checkout_info.should eql Setting.plugin_redmine_checkout[:display_checkout_info] + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/sanity_spec.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe Class do + it "should be a class of Class" do + Class.class.should eql(Class) + end + + it "should be awesome" do + Checkout.awesome?.should be_true + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/spec.opts Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,7 @@ +--colour +--format +progress +--loadby +mtime +--reverse +--backtrace \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/spec_helper.rb Thu Jan 13 13:21:03 2011 +0000 @@ -0,0 +1,27 @@ +ENV['RAILS_ENV'] ||= 'test' + +# prevent case where we are using rubygems and test-unit 2.x is installed +begin + require 'rubygems' + gem "test-unit", "~> 1.2.3" +rescue LoadError +end + +begin + require "config/environment" unless defined? RAILS_ROOT + require RAILS_ROOT + '/spec/spec_helper' +rescue LoadError => error + puts <<-EOS + + You need to install rspec in your Redmine project. + Please execute the following code: + + gem install rspec-rails + script/generate rspec + + EOS + raise error +end + +Fixtures.create_fixtures File.join(File.dirname(__FILE__), "fixtures"), ActiveRecord::Base.connection.tables +require File.join(File.dirname(__FILE__), "..", "init.rb") \ No newline at end of file