You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repositories_helper.rb 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. # Redmine - project management software
  2. # Copyright (C) 2006-2011 Jean-Philippe Lang
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; either version 2
  7. # of the License, or (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. require 'iconv'
  18. require 'redmine/codeset_util'
  19. module RepositoriesHelper
  20. def format_revision(revision)
  21. if revision.respond_to? :format_identifier
  22. revision.format_identifier
  23. else
  24. revision.to_s
  25. end
  26. end
  27. def truncate_at_line_break(text, length = 255)
  28. if text
  29. text.gsub(%r{^(.{#{length}}[^\n]*)\n.+$}m, '\\1...')
  30. end
  31. end
  32. def render_properties(properties)
  33. unless properties.nil? || properties.empty?
  34. content = ''
  35. properties.keys.sort.each do |property|
  36. content << content_tag('li', "<b>#{h property}</b>: <span>#{h properties[property]}</span>")
  37. end
  38. content_tag('ul', content, :class => 'properties')
  39. end
  40. end
  41. def render_changeset_changes
  42. changes = @changeset.changes.find(:all, :limit => 1000, :order => 'path').collect do |change|
  43. case change.action
  44. when 'A'
  45. # Detects moved/copied files
  46. if !change.from_path.blank?
  47. change.action =
  48. @changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
  49. end
  50. change
  51. when 'D'
  52. @changeset.changes.detect {|c| c.from_path == change.path} ? nil : change
  53. else
  54. change
  55. end
  56. end.compact
  57. tree = { }
  58. changes.each do |change|
  59. p = tree
  60. dirs = change.path.to_s.split('/').select {|d| !d.blank?}
  61. path = ''
  62. dirs.each do |dir|
  63. path += '/' + dir
  64. p[:s] ||= {}
  65. p = p[:s]
  66. p[path] ||= {}
  67. p = p[path]
  68. end
  69. p[:c] = change
  70. end
  71. render_changes_tree(tree[:s])
  72. end
  73. def render_changes_tree(tree)
  74. return '' if tree.nil?
  75. output = ''
  76. output << '<ul>'
  77. tree.keys.sort.each do |file|
  78. style = 'change'
  79. text = File.basename(h(file))
  80. if s = tree[file][:s]
  81. style << ' folder'
  82. path_param = to_path_param(@repository.relative_path(file))
  83. text = link_to(h(text), :controller => 'repositories',
  84. :action => 'show',
  85. :id => @project,
  86. :path => path_param,
  87. :rev => @changeset.identifier)
  88. output << "<li class='#{style}'>#{text}</li>"
  89. output << render_changes_tree(s)
  90. elsif c = tree[file][:c]
  91. style << " change-#{c.action}"
  92. path_param = to_path_param(@repository.relative_path(c.path))
  93. text = link_to(h(text), :controller => 'repositories',
  94. :action => 'entry',
  95. :id => @project,
  96. :path => path_param,
  97. :rev => @changeset.identifier) unless c.action == 'D'
  98. text << " - #{h(c.revision)}" unless c.revision.blank?
  99. text << ' (' + link_to(l(:label_diff), :controller => 'repositories',
  100. :action => 'diff',
  101. :id => @project,
  102. :path => path_param,
  103. :rev => @changeset.identifier) + ') ' if c.action == 'M'
  104. text << ' ' + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank?
  105. output << "<li class='#{style}'>#{text}</li>"
  106. end
  107. end
  108. output << '</ul>'
  109. output
  110. end
  111. def to_utf8(str)
  112. return str if str.nil?
  113. str = to_utf8_internal(str)
  114. if str.respond_to?(:force_encoding)
  115. str.force_encoding('UTF-8')
  116. end
  117. str
  118. end
  119. def to_utf8_internal(str)
  120. return str if str.nil?
  121. if str.respond_to?(:force_encoding)
  122. str.force_encoding('ASCII-8BIT')
  123. end
  124. return str if str.empty?
  125. return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
  126. if str.respond_to?(:force_encoding)
  127. str.force_encoding('UTF-8')
  128. end
  129. @encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
  130. @encodings.each do |encoding|
  131. begin
  132. return Iconv.conv('UTF-8', encoding, str)
  133. rescue Iconv::Failure
  134. # do nothing here and try the next encoding
  135. end
  136. end
  137. str = Redmine::CodesetUtil.replace_invalid_utf8(str)
  138. end
  139. private :to_utf8_internal
  140. def repository_field_tags(form, repository)
  141. method = repository.class.name.demodulize.underscore + "_field_tags"
  142. if repository.is_a?(Repository) &&
  143. respond_to?(method) && method != 'repository_field_tags'
  144. send(method, form, repository)
  145. end
  146. end
  147. def scm_select_tag(repository)
  148. scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']]
  149. Redmine::Scm::Base.all.each do |scm|
  150. if Setting.enabled_scm.include?(scm) ||
  151. (repository && repository.class.name.demodulize == scm)
  152. scm_options << ["Repository::#{scm}".constantize.scm_name, scm]
  153. end
  154. end
  155. select_tag('repository_scm',
  156. options_for_select(scm_options, repository.class.name.demodulize),
  157. :disabled => (repository && !repository.new_record?),
  158. :onchange => remote_function(
  159. :url => {
  160. :controller => 'repositories',
  161. :action => 'edit',
  162. :id => @project
  163. },
  164. :method => :get,
  165. :with => "Form.serialize(this.form)")
  166. )
  167. end
  168. def with_leading_slash(path)
  169. path.to_s.starts_with?('/') ? path : "/#{path}"
  170. end
  171. def without_leading_slash(path)
  172. path.gsub(%r{^/+}, '')
  173. end
  174. def subversion_field_tags(form, repository)
  175. content_tag('p', form.text_field(:url, :size => 60, :required => true,
  176. :disabled => (repository && !repository.root_url.blank?)) +
  177. '<br />(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
  178. content_tag('p', form.text_field(:login, :size => 30)) +
  179. content_tag('p', form.password_field(
  180. :password, :size => 30, :name => 'ignore',
  181. :value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)),
  182. :onfocus => "this.value=''; this.name='repository[password]';",
  183. :onchange => "this.name='repository[password]';"))
  184. end
  185. def darcs_field_tags(form, repository)
  186. content_tag('p', form.text_field(
  187. :url, :label => l(:field_path_to_repository),
  188. :size => 60, :required => true,
  189. :disabled => (repository && !repository.new_record?))) +
  190. content_tag('p', form.select(
  191. :log_encoding, [nil] + Setting::ENCODINGS,
  192. :label => l(:field_commit_logs_encoding), :required => true))
  193. end
  194. def mercurial_field_tags(form, repository)
  195. content_tag('p', form.text_field(
  196. :url, :label => l(:field_path_to_repository),
  197. :size => 60, :required => true,
  198. :disabled => (repository && !repository.root_url.blank?)
  199. ) +
  200. '<br />' + l(:text_mercurial_repository_note)) +
  201. content_tag('p', form.select(
  202. :path_encoding, [nil] + Setting::ENCODINGS,
  203. :label => l(:field_scm_path_encoding)
  204. ) +
  205. '<br />' + l(:text_scm_path_encoding_note))
  206. end
  207. def git_field_tags(form, repository)
  208. content_tag('p', form.text_field(
  209. :url, :label => l(:field_path_to_repository),
  210. :size => 60, :required => true,
  211. :disabled => (repository && !repository.root_url.blank?)
  212. ) +
  213. '<br />' +
  214. l(:text_git_repository_note)) +
  215. content_tag('p', form.select(
  216. :path_encoding, [nil] + Setting::ENCODINGS,
  217. :label => l(:field_scm_path_encoding)
  218. ) +
  219. '<br />' + l(:text_scm_path_encoding_note)) +
  220. content_tag('p', form.check_box(
  221. :extra_report_last_commit,
  222. :label => l(:label_git_report_last_commit)
  223. ))
  224. end
  225. def cvs_field_tags(form, repository)
  226. content_tag('p', form.text_field(
  227. :root_url,
  228. :label => l(:field_cvsroot),
  229. :size => 60, :required => true,
  230. :disabled => !repository.new_record?)) +
  231. content_tag('p', form.text_field(
  232. :url,
  233. :label => l(:field_cvs_module),
  234. :size => 30, :required => true,
  235. :disabled => !repository.new_record?)) +
  236. content_tag('p', form.select(
  237. :log_encoding, [nil] + Setting::ENCODINGS,
  238. :label => l(:field_commit_logs_encoding), :required => true)) +
  239. content_tag('p', form.select(
  240. :path_encoding, [nil] + Setting::ENCODINGS,
  241. :label => l(:field_scm_path_encoding)
  242. ) +
  243. '<br />' + l(:text_scm_path_encoding_note))
  244. end
  245. def bazaar_field_tags(form, repository)
  246. content_tag('p', form.text_field(
  247. :url, :label => l(:field_path_to_repository),
  248. :size => 60, :required => true,
  249. :disabled => (repository && !repository.new_record?))) +
  250. content_tag('p', form.select(
  251. :log_encoding, [nil] + Setting::ENCODINGS,
  252. :label => l(:field_commit_logs_encoding), :required => true))
  253. end
  254. def filesystem_field_tags(form, repository)
  255. content_tag('p', form.text_field(
  256. :url, :label => l(:field_root_directory),
  257. :size => 60, :required => true,
  258. :disabled => (repository && !repository.root_url.blank?))) +
  259. content_tag('p', form.select(
  260. :path_encoding, [nil] + Setting::ENCODINGS,
  261. :label => l(:field_scm_path_encoding)
  262. ) +
  263. '<br />' + l(:text_scm_path_encoding_note))
  264. end
  265. end