@@ -152,7 +152,7 module RepositoriesHelper | |||||
152 | def subversion_field_tags(form, repository) |
|
152 | def subversion_field_tags(form, repository) | |
153 | content_tag('p', form.text_field(:url, :size => 60, :required => true, |
|
153 | content_tag('p', form.text_field(:url, :size => 60, :required => true, | |
154 | :disabled => !repository.safe_attribute?('url')) + |
|
154 | :disabled => !repository.safe_attribute?('url')) + | |
155 | content_tag('em', '(file:///, http://, https://, svn://, svn+[tunnelscheme]://)', :class => 'info')) + |
|
155 | scm_path_info_tag(repository)) + | |
156 | content_tag('p', form.text_field(:login, :size => 30)) + |
|
156 | content_tag('p', form.text_field(:login, :size => 30)) + | |
157 | content_tag('p', form.password_field( |
|
157 | content_tag('p', form.password_field( | |
158 | :password, :size => 30, :name => 'ignore', |
|
158 | :password, :size => 30, :name => 'ignore', | |
@@ -165,7 +165,8 module RepositoriesHelper | |||||
165 | content_tag('p', form.text_field( |
|
165 | content_tag('p', form.text_field( | |
166 | :url, :label => l(:field_path_to_repository), |
|
166 | :url, :label => l(:field_path_to_repository), | |
167 | :size => 60, :required => true, |
|
167 | :size => 60, :required => true, | |
168 |
:disabled => !repository.safe_attribute?('url')) |
|
168 | :disabled => !repository.safe_attribute?('url')) + | |
|
169 | scm_path_info_tag(repository)) + | |||
169 | scm_log_encoding_tag(form, repository) |
|
170 | scm_log_encoding_tag(form, repository) | |
170 | end |
|
171 | end | |
171 |
|
172 | |||
@@ -175,7 +176,7 module RepositoriesHelper | |||||
175 | :size => 60, :required => true, |
|
176 | :size => 60, :required => true, | |
176 | :disabled => !repository.safe_attribute?('url') |
|
177 | :disabled => !repository.safe_attribute?('url') | |
177 | ) + |
|
178 | ) + | |
178 | content_tag('em', l(:text_mercurial_repository_note), :class => 'info')) + |
|
179 | scm_path_info_tag(repository)) + | |
179 | scm_path_encoding_tag(form, repository) |
|
180 | scm_path_encoding_tag(form, repository) | |
180 | end |
|
181 | end | |
181 |
|
182 | |||
@@ -185,7 +186,7 module RepositoriesHelper | |||||
185 | :size => 60, :required => true, |
|
186 | :size => 60, :required => true, | |
186 | :disabled => !repository.safe_attribute?('url') |
|
187 | :disabled => !repository.safe_attribute?('url') | |
187 | ) + |
|
188 | ) + | |
188 | content_tag('em', l(:text_git_repository_note), :class => 'info')) + |
|
189 | scm_path_info_tag(repository)) + | |
189 | scm_path_encoding_tag(form, repository) + |
|
190 | scm_path_encoding_tag(form, repository) + | |
190 | content_tag('p', form.check_box( |
|
191 | content_tag('p', form.check_box( | |
191 | :extra_report_last_commit, |
|
192 | :extra_report_last_commit, | |
@@ -198,7 +199,8 module RepositoriesHelper | |||||
198 | :root_url, |
|
199 | :root_url, | |
199 | :label => l(:field_cvsroot), |
|
200 | :label => l(:field_cvsroot), | |
200 | :size => 60, :required => true, |
|
201 | :size => 60, :required => true, | |
201 |
:disabled => !repository.safe_attribute?('root_url')) |
|
202 | :disabled => !repository.safe_attribute?('root_url')) + | |
|
203 | scm_path_info_tag(repository)) + | |||
202 | content_tag('p', form.text_field( |
|
204 | content_tag('p', form.text_field( | |
203 | :url, |
|
205 | :url, | |
204 | :label => l(:field_cvs_module), |
|
206 | :label => l(:field_cvs_module), | |
@@ -212,7 +214,8 module RepositoriesHelper | |||||
212 | content_tag('p', form.text_field( |
|
214 | content_tag('p', form.text_field( | |
213 | :url, :label => l(:field_path_to_repository), |
|
215 | :url, :label => l(:field_path_to_repository), | |
214 | :size => 60, :required => true, |
|
216 | :size => 60, :required => true, | |
215 |
:disabled => !repository.safe_attribute?('url')) |
|
217 | :disabled => !repository.safe_attribute?('url')) + | |
|
218 | scm_path_info_tag(repository)) + | |||
216 | scm_log_encoding_tag(form, repository) |
|
219 | scm_log_encoding_tag(form, repository) | |
217 | end |
|
220 | end | |
218 |
|
221 | |||
@@ -220,10 +223,29 module RepositoriesHelper | |||||
220 | content_tag('p', form.text_field( |
|
223 | content_tag('p', form.text_field( | |
221 | :url, :label => l(:field_root_directory), |
|
224 | :url, :label => l(:field_root_directory), | |
222 | :size => 60, :required => true, |
|
225 | :size => 60, :required => true, | |
223 |
:disabled => !repository.safe_attribute?('url')) |
|
226 | :disabled => !repository.safe_attribute?('url')) + | |
|
227 | scm_path_info_tag(repository)) + | |||
224 | scm_path_encoding_tag(form, repository) |
|
228 | scm_path_encoding_tag(form, repository) | |
225 | end |
|
229 | end | |
226 |
|
230 | |||
|
231 | def scm_path_info_tag(repository) | |||
|
232 | text = scm_path_info(repository) | |||
|
233 | if text.present? | |||
|
234 | content_tag('em', text, :class => 'info') | |||
|
235 | else | |||
|
236 | '' | |||
|
237 | end | |||
|
238 | end | |||
|
239 | ||||
|
240 | def scm_path_info(repository) | |||
|
241 | scm_name = repository.scm_name.to_s.downcase | |||
|
242 | ||||
|
243 | info_from_config = Redmine::Configuration["scm_#{scm_name}_path_info"].presence | |||
|
244 | return info_from_config.html_safe if info_from_config | |||
|
245 | ||||
|
246 | l("text_#{scm_name}_repository_note", :default => '') | |||
|
247 | end | |||
|
248 | ||||
227 | def scm_log_encoding_tag(form, repository) |
|
249 | def scm_log_encoding_tag(form, repository) | |
228 | select = form.select( |
|
250 | select = form.select( | |
229 | :log_encoding, |
|
251 | :log_encoding, |
@@ -45,6 +45,7 class Repository < ActiveRecord::Base | |||||
45 | validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true |
|
45 | validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true | |
46 | # Checks if the SCM is enabled when creating a repository |
|
46 | # Checks if the SCM is enabled when creating a repository | |
47 | validate :repo_create_validation, :on => :create |
|
47 | validate :repo_create_validation, :on => :create | |
|
48 | validate :validate_repository_path | |||
48 | attr_protected :id |
|
49 | attr_protected :id | |
49 |
|
50 | |||
50 | safe_attributes 'identifier', |
|
51 | safe_attributes 'identifier', | |
@@ -458,6 +459,18 class Repository < ActiveRecord::Base | |||||
458 |
|
459 | |||
459 | protected |
|
460 | protected | |
460 |
|
461 | |||
|
462 | # Validates repository url based against an optional regular expression | |||
|
463 | # that can be set in the Redmine configuration file. | |||
|
464 | def validate_repository_path(attribute=:url) | |||
|
465 | regexp = Redmine::Configuration["scm_#{scm_name.to_s.downcase}_path_regexp"] | |||
|
466 | if changes[attribute] && regexp.present? | |||
|
467 | regexp = regexp.to_s.strip.gsub('%project%') {Regexp.escape(project.try(:identifier).to_s)} | |||
|
468 | unless send(attribute).to_s.match(Regexp.new("\\A#{regexp}\\z")) | |||
|
469 | errors.add(attribute, :invalid) | |||
|
470 | end | |||
|
471 | end | |||
|
472 | end | |||
|
473 | ||||
461 | def check_default |
|
474 | def check_default | |
462 | if !is_default? && set_as_default? |
|
475 | if !is_default? && set_as_default? | |
463 | self.is_default = true |
|
476 | self.is_default = true |
@@ -192,6 +192,14 class Repository::Cvs < Repository | |||||
192 | @current_revision_number = nil |
|
192 | @current_revision_number = nil | |
193 | end |
|
193 | end | |
194 |
|
194 | |||
|
195 | protected | |||
|
196 | ||||
|
197 | # Overrides Repository#validate_repository_path to validate | |||
|
198 | # against root_url attribute. | |||
|
199 | def validate_repository_path(attribute=:root_url) | |||
|
200 | super(attribute) | |||
|
201 | end | |||
|
202 | ||||
195 | private |
|
203 | private | |
196 |
|
204 | |||
197 | # Returns the next revision number to assign to a CVS changeset |
|
205 | # Returns the next revision number to assign to a CVS changeset |
@@ -108,6 +108,33 default: | |||||
108 | scm_bazaar_command: |
|
108 | scm_bazaar_command: | |
109 | scm_darcs_command: |
|
109 | scm_darcs_command: | |
110 |
|
110 | |||
|
111 | # SCM paths validation. | |||
|
112 | # | |||
|
113 | # You can configure a regular expression for each SCM that will be used to | |||
|
114 | # validate the path of new repositories (eg. path entered by users with the | |||
|
115 | # "Manage repositories" permission and path returned by reposman.rb). | |||
|
116 | # The regexp will be wrapped with \A \z, so it must match the whole path. | |||
|
117 | # And the regexp is case sensitive. | |||
|
118 | # | |||
|
119 | # You can match the project identifier by using %project% in the regexp. | |||
|
120 | # | |||
|
121 | # You can also set a custom hint message for each SCM that will be displayed | |||
|
122 | # on the repository form instead of the default one. | |||
|
123 | # | |||
|
124 | # Examples: | |||
|
125 | # scm_subversion_path_regexp: file:///svnpath/[a-z0-9_]+ | |||
|
126 | # scm_subversion_path_info: SVN URL (eg. file:///svnpath/foo) | |||
|
127 | # | |||
|
128 | # scm_git_path_regexp: /gitpath/%project%(\.[a-z0-9_])?/ | |||
|
129 | # | |||
|
130 | scm_subversion_path_regexp: | |||
|
131 | scm_mercurial_path_regexp: | |||
|
132 | scm_git_path_regexp: | |||
|
133 | scm_cvs_path_regexp: | |||
|
134 | scm_bazaar_path_regexp: | |||
|
135 | scm_darcs_path_regexp: | |||
|
136 | scm_filesystem_path_regexp: | |||
|
137 | ||||
111 | # Absolute path to the SCM commands errors (stderr) log file. |
|
138 | # Absolute path to the SCM commands errors (stderr) log file. | |
112 | # The default is to log in the 'log' directory of your Redmine instance. |
|
139 | # The default is to log in the 'log' directory of your Redmine instance. | |
113 | # Example: |
|
140 | # Example: |
@@ -1052,6 +1052,7 en: | |||||
1052 | text_zoom_out: Zoom out |
|
1052 | text_zoom_out: Zoom out | |
1053 | text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page." |
|
1053 | text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page." | |
1054 | text_scm_path_encoding_note: "Default: UTF-8" |
|
1054 | text_scm_path_encoding_note: "Default: UTF-8" | |
|
1055 | text_subversion_repository_note: "Examples: file:///, http://, https://, svn://, svn+[tunnelscheme]://" | |||
1055 | text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo) |
|
1056 | text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo) | |
1056 | text_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo) |
|
1057 | text_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo) | |
1057 | text_scm_command: Command |
|
1058 | text_scm_command: Command |
@@ -1072,8 +1072,9 fr: | |||||
1072 | text_zoom_out: Zoom arrière |
|
1072 | text_zoom_out: Zoom arrière | |
1073 | text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardΓ© qui sera perdu si vous quittez la page." |
|
1073 | text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardΓ© qui sera perdu si vous quittez la page." | |
1074 | text_scm_path_encoding_note: "DΓ©faut : UTF-8" |
|
1074 | text_scm_path_encoding_note: "DΓ©faut : UTF-8" | |
1075 | text_git_repository_note: "Le dΓ©pΓ΄t est vide et local (exemples : /gitrepo, c:\\gitrepo)" |
|
1075 | text_subversion_repository_note: "Exemples (en fonction des protocoles supportΓ©s) : file:///, http://, https://, svn://, svn+[tunnelscheme]://" | |
1076 |
text_ |
|
1076 | text_git_repository_note: "Chemin vers un dΓ©pΓ΄t vide et local (exemples : /gitrepo, c:\\gitrepo)" | |
|
1077 | text_mercurial_repository_note: "Chemin vers un dΓ©pΓ΄t local (exemples : /hgrepo, c:\\hgrepo)" | |||
1077 | text_scm_command: Commande |
|
1078 | text_scm_command: Commande | |
1078 | text_scm_command_version: Version |
|
1079 | text_scm_command_version: Version | |
1079 | text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification. |
|
1080 | text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification. |
@@ -58,6 +58,7 module Redmine | |||||
58 | end |
|
58 | end | |
59 | end |
|
59 | end | |
60 |
|
60 | |||
|
61 | check_regular_expressions | |||
61 | @config |
|
62 | @config | |
62 | end |
|
63 | end | |
63 |
|
64 | |||
@@ -112,6 +113,20 module Redmine | |||||
112 | @config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)}) |
|
113 | @config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)}) | |
113 | end |
|
114 | end | |
114 | end |
|
115 | end | |
|
116 | ||||
|
117 | # Checks the validness of regular expressions set for repository paths at startup | |||
|
118 | def check_regular_expressions | |||
|
119 | @config.each do |name, value| | |||
|
120 | if value.present? && name =~ /^scm_.+_path_regexp$/ | |||
|
121 | begin | |||
|
122 | Regexp.new value.to_s.strip | |||
|
123 | rescue => e | |||
|
124 | $stderr.puts "Invalid regular expression set as #{name} setting in your Redmine configuration file:\n#{e.message}" | |||
|
125 | exit 1 | |||
|
126 | end | |||
|
127 | end | |||
|
128 | end | |||
|
129 | end | |||
115 | end |
|
130 | end | |
116 | end |
|
131 | end | |
117 | end |
|
132 | end |
@@ -93,6 +93,24 class RepositoryCvsTest < ActiveSupport::TestCase | |||||
93 | assert_include str, repo.errors.full_messages |
|
93 | assert_include str, repo.errors.full_messages | |
94 | end |
|
94 | end | |
95 |
|
95 | |||
|
96 | def test_root_url_should_be_validated_against_regexp_set_in_configuration | |||
|
97 | Redmine::Configuration.with 'scm_cvs_path_regexp' => '/cvspath/[a-z]+' do | |||
|
98 | repo = Repository::Cvs.new( | |||
|
99 | :project => @project, | |||
|
100 | :identifier => 'test', | |||
|
101 | :log_encoding => 'UTF-8', | |||
|
102 | :path_encoding => '', | |||
|
103 | :url => MODULE_NAME | |||
|
104 | ) | |||
|
105 | repo.root_url = '/wrong_path' | |||
|
106 | assert !repo.valid? | |||
|
107 | assert repo.errors[:root_url].present? | |||
|
108 | ||||
|
109 | repo.root_url = '/cvspath/foo' | |||
|
110 | assert repo.valid? | |||
|
111 | end | |||
|
112 | end | |||
|
113 | ||||
96 | if File.directory?(REPOSITORY_PATH) |
|
114 | if File.directory?(REPOSITORY_PATH) | |
97 | def test_fetch_changesets_from_scratch |
|
115 | def test_fetch_changesets_from_scratch | |
98 | assert_equal 0, @repository.changesets.count |
|
116 | assert_equal 0, @repository.changesets.count |
@@ -57,6 +57,37 class RepositorySubversionTest < ActiveSupport::TestCase | |||||
57 | end |
|
57 | end | |
58 | end |
|
58 | end | |
59 |
|
59 | |||
|
60 | def test_url_should_be_validated_against_regexp_set_in_configuration | |||
|
61 | Redmine::Configuration.with 'scm_subversion_path_regexp' => 'file:///svnpath/[a-z]+' do | |||
|
62 | repo = Repository::Subversion.new(:project => @project, :identifier => 'test') | |||
|
63 | repo.url = 'http://foo' | |||
|
64 | assert !repo.valid? | |||
|
65 | assert repo.errors[:url].present? | |||
|
66 | ||||
|
67 | repo.url = 'file:///svnpath/foo/bar' | |||
|
68 | assert !repo.valid? | |||
|
69 | assert repo.errors[:url].present? | |||
|
70 | ||||
|
71 | repo.url = 'file:///svnpath/foo' | |||
|
72 | assert repo.valid? | |||
|
73 | end | |||
|
74 | end | |||
|
75 | ||||
|
76 | def test_url_should_be_validated_against_regexp_set_in_configuration_with_project_identifier | |||
|
77 | Redmine::Configuration.with 'scm_subversion_path_regexp' => 'file:///svnpath/%project%(\.[a-z]+)?' do | |||
|
78 | repo = Repository::Subversion.new(:project => @project, :identifier => 'test') | |||
|
79 | repo.url = 'file:///svnpath/invalid' | |||
|
80 | assert !repo.valid? | |||
|
81 | assert repo.errors[:url].present? | |||
|
82 | ||||
|
83 | repo.url = 'file:///svnpath/subproject1' | |||
|
84 | assert repo.valid? | |||
|
85 | ||||
|
86 | repo.url = 'file:///svnpath/subproject1.foo' | |||
|
87 | assert repo.valid? | |||
|
88 | end | |||
|
89 | end | |||
|
90 | ||||
60 | if repository_configured?('subversion') |
|
91 | if repository_configured?('subversion') | |
61 | def test_fetch_changesets_from_scratch |
|
92 | def test_fetch_changesets_from_scratch | |
62 | assert_equal 0, @repository.changesets.count |
|
93 | assert_equal 0, @repository.changesets.count |
General Comments 0
You need to be logged in to leave comments.
Login now