summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/helpers/repositories_helper.rb36
-rw-r--r--app/models/repository.rb13
-rw-r--r--app/models/repository/cvs.rb8
-rw-r--r--config/configuration.yml.example27
-rw-r--r--config/locales/en.yml1
-rw-r--r--config/locales/fr.yml5
-rw-r--r--lib/redmine/configuration.rb15
-rw-r--r--test/unit/repository_cvs_test.rb18
-rw-r--r--test/unit/repository_subversion_test.rb31
9 files changed, 145 insertions, 9 deletions
diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb
index 32b72ec54..ebe73da3f 100644
--- a/app/helpers/repositories_helper.rb
+++ b/app/helpers/repositories_helper.rb
@@ -152,7 +152,7 @@ module RepositoriesHelper
def subversion_field_tags(form, repository)
content_tag('p', form.text_field(:url, :size => 60, :required => true,
:disabled => !repository.safe_attribute?('url')) +
- content_tag('em', '(file:///, http://, https://, svn://, svn+[tunnelscheme]://)', :class => 'info')) +
+ scm_path_info_tag(repository)) +
content_tag('p', form.text_field(:login, :size => 30)) +
content_tag('p', form.password_field(
:password, :size => 30, :name => 'ignore',
@@ -165,7 +165,8 @@ module RepositoriesHelper
content_tag('p', form.text_field(
:url, :label => l(:field_path_to_repository),
:size => 60, :required => true,
- :disabled => !repository.safe_attribute?('url'))) +
+ :disabled => !repository.safe_attribute?('url')) +
+ scm_path_info_tag(repository)) +
scm_log_encoding_tag(form, repository)
end
@@ -175,7 +176,7 @@ module RepositoriesHelper
:size => 60, :required => true,
:disabled => !repository.safe_attribute?('url')
) +
- content_tag('em', l(:text_mercurial_repository_note), :class => 'info')) +
+ scm_path_info_tag(repository)) +
scm_path_encoding_tag(form, repository)
end
@@ -185,7 +186,7 @@ module RepositoriesHelper
:size => 60, :required => true,
:disabled => !repository.safe_attribute?('url')
) +
- content_tag('em', l(:text_git_repository_note), :class => 'info')) +
+ scm_path_info_tag(repository)) +
scm_path_encoding_tag(form, repository) +
content_tag('p', form.check_box(
:extra_report_last_commit,
@@ -198,7 +199,8 @@ module RepositoriesHelper
:root_url,
:label => l(:field_cvsroot),
:size => 60, :required => true,
- :disabled => !repository.safe_attribute?('root_url'))) +
+ :disabled => !repository.safe_attribute?('root_url')) +
+ scm_path_info_tag(repository)) +
content_tag('p', form.text_field(
:url,
:label => l(:field_cvs_module),
@@ -212,7 +214,8 @@ module RepositoriesHelper
content_tag('p', form.text_field(
:url, :label => l(:field_path_to_repository),
:size => 60, :required => true,
- :disabled => !repository.safe_attribute?('url'))) +
+ :disabled => !repository.safe_attribute?('url')) +
+ scm_path_info_tag(repository)) +
scm_log_encoding_tag(form, repository)
end
@@ -220,10 +223,29 @@ module RepositoriesHelper
content_tag('p', form.text_field(
:url, :label => l(:field_root_directory),
:size => 60, :required => true,
- :disabled => !repository.safe_attribute?('url'))) +
+ :disabled => !repository.safe_attribute?('url')) +
+ scm_path_info_tag(repository)) +
scm_path_encoding_tag(form, repository)
end
+ def scm_path_info_tag(repository)
+ text = scm_path_info(repository)
+ if text.present?
+ content_tag('em', text, :class => 'info')
+ else
+ ''
+ end
+ end
+
+ def scm_path_info(repository)
+ scm_name = repository.scm_name.to_s.downcase
+
+ info_from_config = Redmine::Configuration["scm_#{scm_name}_path_info"].presence
+ return info_from_config.html_safe if info_from_config
+
+ l("text_#{scm_name}_repository_note", :default => '')
+ end
+
def scm_log_encoding_tag(form, repository)
select = form.select(
:log_encoding,
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 1cab86bd1..4d81c47ab 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -45,6 +45,7 @@ class Repository < ActiveRecord::Base
validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
# Checks if the SCM is enabled when creating a repository
validate :repo_create_validation, :on => :create
+ validate :validate_repository_path
attr_protected :id
safe_attributes 'identifier',
@@ -458,6 +459,18 @@ class Repository < ActiveRecord::Base
protected
+ # Validates repository url based against an optional regular expression
+ # that can be set in the Redmine configuration file.
+ def validate_repository_path(attribute=:url)
+ regexp = Redmine::Configuration["scm_#{scm_name.to_s.downcase}_path_regexp"]
+ if changes[attribute] && regexp.present?
+ regexp = regexp.to_s.strip.gsub('%project%') {Regexp.escape(project.try(:identifier).to_s)}
+ unless send(attribute).to_s.match(Regexp.new("\\A#{regexp}\\z"))
+ errors.add(attribute, :invalid)
+ end
+ end
+ end
+
def check_default
if !is_default? && set_as_default?
self.is_default = true
diff --git a/app/models/repository/cvs.rb b/app/models/repository/cvs.rb
index abc408304..991c0449c 100644
--- a/app/models/repository/cvs.rb
+++ b/app/models/repository/cvs.rb
@@ -192,6 +192,14 @@ class Repository::Cvs < Repository
@current_revision_number = nil
end
+ protected
+
+ # Overrides Repository#validate_repository_path to validate
+ # against root_url attribute.
+ def validate_repository_path(attribute=:root_url)
+ super(attribute)
+ end
+
private
# Returns the next revision number to assign to a CVS changeset
diff --git a/config/configuration.yml.example b/config/configuration.yml.example
index da209f0bd..e6a8c6e20 100644
--- a/config/configuration.yml.example
+++ b/config/configuration.yml.example
@@ -108,6 +108,33 @@ default:
scm_bazaar_command:
scm_darcs_command:
+ # SCM paths validation.
+ #
+ # You can configure a regular expression for each SCM that will be used to
+ # validate the path of new repositories (eg. path entered by users with the
+ # "Manage repositories" permission and path returned by reposman.rb).
+ # The regexp will be wrapped with \A \z, so it must match the whole path.
+ # And the regexp is case sensitive.
+ #
+ # You can match the project identifier by using %project% in the regexp.
+ #
+ # You can also set a custom hint message for each SCM that will be displayed
+ # on the repository form instead of the default one.
+ #
+ # Examples:
+ # scm_subversion_path_regexp: file:///svnpath/[a-z0-9_]+
+ # scm_subversion_path_info: SVN URL (eg. file:///svnpath/foo)
+ #
+ # scm_git_path_regexp: /gitpath/%project%(\.[a-z0-9_])?/
+ #
+ scm_subversion_path_regexp:
+ scm_mercurial_path_regexp:
+ scm_git_path_regexp:
+ scm_cvs_path_regexp:
+ scm_bazaar_path_regexp:
+ scm_darcs_path_regexp:
+ scm_filesystem_path_regexp:
+
# Absolute path to the SCM commands errors (stderr) log file.
# The default is to log in the 'log' directory of your Redmine instance.
# Example:
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 66de43259..f0372bccf 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1052,6 +1052,7 @@ en:
text_zoom_out: Zoom out
text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page."
text_scm_path_encoding_note: "Default: UTF-8"
+ text_subversion_repository_note: "Examples: file:///, http://, https://, svn://, svn+[tunnelscheme]://"
text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo)
text_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo)
text_scm_command: Command
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index e575388e8..25693d080 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -1072,8 +1072,9 @@ fr:
text_zoom_out: Zoom arrière
text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardé qui sera perdu si vous quittez la page."
text_scm_path_encoding_note: "Défaut : UTF-8"
- text_git_repository_note: "Le dépôt est vide et local (exemples : /gitrepo, c:\\gitrepo)"
- text_mercurial_repository_note: "Dépôt local (exemples : /hgrepo, c:\\hgrepo)"
+ text_subversion_repository_note: "Exemples (en fonction des protocoles supportés) : file:///, http://, https://, svn://, svn+[tunnelscheme]://"
+ text_git_repository_note: "Chemin vers un dépôt vide et local (exemples : /gitrepo, c:\\gitrepo)"
+ text_mercurial_repository_note: "Chemin vers un dépôt local (exemples : /hgrepo, c:\\hgrepo)"
text_scm_command: Commande
text_scm_command_version: Version
text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification.
diff --git a/lib/redmine/configuration.rb b/lib/redmine/configuration.rb
index 01abf4e93..77bdd8fd0 100644
--- a/lib/redmine/configuration.rb
+++ b/lib/redmine/configuration.rb
@@ -58,6 +58,7 @@ module Redmine
end
end
+ check_regular_expressions
@config
end
@@ -112,6 +113,20 @@ module Redmine
@config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)})
end
end
+
+ # Checks the validness of regular expressions set for repository paths at startup
+ def check_regular_expressions
+ @config.each do |name, value|
+ if value.present? && name =~ /^scm_.+_path_regexp$/
+ begin
+ Regexp.new value.to_s.strip
+ rescue => e
+ $stderr.puts "Invalid regular expression set as #{name} setting in your Redmine configuration file:\n#{e.message}"
+ exit 1
+ end
+ end
+ end
+ end
end
end
end
diff --git a/test/unit/repository_cvs_test.rb b/test/unit/repository_cvs_test.rb
index 8b5ac6271..fec41329a 100644
--- a/test/unit/repository_cvs_test.rb
+++ b/test/unit/repository_cvs_test.rb
@@ -93,6 +93,24 @@ class RepositoryCvsTest < ActiveSupport::TestCase
assert_include str, repo.errors.full_messages
end
+ def test_root_url_should_be_validated_against_regexp_set_in_configuration
+ Redmine::Configuration.with 'scm_cvs_path_regexp' => '/cvspath/[a-z]+' do
+ repo = Repository::Cvs.new(
+ :project => @project,
+ :identifier => 'test',
+ :log_encoding => 'UTF-8',
+ :path_encoding => '',
+ :url => MODULE_NAME
+ )
+ repo.root_url = '/wrong_path'
+ assert !repo.valid?
+ assert repo.errors[:root_url].present?
+
+ repo.root_url = '/cvspath/foo'
+ assert repo.valid?
+ end
+ end
+
if File.directory?(REPOSITORY_PATH)
def test_fetch_changesets_from_scratch
assert_equal 0, @repository.changesets.count
diff --git a/test/unit/repository_subversion_test.rb b/test/unit/repository_subversion_test.rb
index 2fe50da14..42e963288 100644
--- a/test/unit/repository_subversion_test.rb
+++ b/test/unit/repository_subversion_test.rb
@@ -57,6 +57,37 @@ class RepositorySubversionTest < ActiveSupport::TestCase
end
end
+ def test_url_should_be_validated_against_regexp_set_in_configuration
+ Redmine::Configuration.with 'scm_subversion_path_regexp' => 'file:///svnpath/[a-z]+' do
+ repo = Repository::Subversion.new(:project => @project, :identifier => 'test')
+ repo.url = 'http://foo'
+ assert !repo.valid?
+ assert repo.errors[:url].present?
+
+ repo.url = 'file:///svnpath/foo/bar'
+ assert !repo.valid?
+ assert repo.errors[:url].present?
+
+ repo.url = 'file:///svnpath/foo'
+ assert repo.valid?
+ end
+ end
+
+ def test_url_should_be_validated_against_regexp_set_in_configuration_with_project_identifier
+ Redmine::Configuration.with 'scm_subversion_path_regexp' => 'file:///svnpath/%project%(\.[a-z]+)?' do
+ repo = Repository::Subversion.new(:project => @project, :identifier => 'test')
+ repo.url = 'file:///svnpath/invalid'
+ assert !repo.valid?
+ assert repo.errors[:url].present?
+
+ repo.url = 'file:///svnpath/subproject1'
+ assert repo.valid?
+
+ repo.url = 'file:///svnpath/subproject1.foo'
+ assert repo.valid?
+ end
+ end
+
if repository_configured?('subversion')
def test_fetch_changesets_from_scratch
assert_equal 0, @repository.changesets.count