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.

subversion.rb 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. # frozen_string_literal: true
  2. # Redmine - project management software
  3. # Copyright (C) 2006-2017 Jean-Philippe Lang
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU General Public License
  7. # as published by the Free Software Foundation; either version 2
  8. # of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. require 'redmine/scm/adapters/subversion_adapter'
  19. class Repository::Subversion < Repository
  20. validates_presence_of :url
  21. validates_format_of :url, :with => %r{\A(http|https|svn(\+[^\s:\/\\]+)?|file):\/\/.+}i
  22. def self.scm_adapter_class
  23. Redmine::Scm::Adapters::SubversionAdapter
  24. end
  25. def self.scm_name
  26. 'Subversion'
  27. end
  28. def supports_directory_revisions?
  29. true
  30. end
  31. def repo_log_encoding
  32. 'UTF-8'
  33. end
  34. def latest_changesets(path, rev, limit=10)
  35. revisions = scm.revisions(path, rev, nil, :limit => limit)
  36. if revisions
  37. identifiers = revisions.collect(&:identifier).compact
  38. changesets.where(:revision => identifiers).reorder("committed_on DESC").includes(:repository, :user).to_a
  39. else
  40. []
  41. end
  42. end
  43. # Returns a path relative to the url of the repository
  44. def relative_path(path)
  45. path.gsub(Regexp.new("^\/?#{Regexp.escape(relative_url)}"), '')
  46. end
  47. def fetch_changesets
  48. scm_info = scm.info
  49. if scm_info
  50. # latest revision found in database
  51. db_revision = latest_changeset ? latest_changeset.revision.to_i : 0
  52. # latest revision in the repository
  53. scm_revision = scm_info.lastrev.identifier.to_i
  54. if db_revision < scm_revision
  55. logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
  56. identifier_from = db_revision + 1
  57. while (identifier_from <= scm_revision)
  58. # loads changesets by batches of 200
  59. identifier_to = [identifier_from + 199, scm_revision].min
  60. revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
  61. revisions.reverse_each do |revision|
  62. transaction do
  63. changeset = Changeset.create(:repository => self,
  64. :revision => revision.identifier,
  65. :committer => revision.author,
  66. :committed_on => revision.time,
  67. :comments => revision.message)
  68. revision.paths.each do |change|
  69. changeset.create_change(change)
  70. end unless changeset.new_record?
  71. end
  72. end unless revisions.nil?
  73. identifier_from = identifier_to + 1
  74. end
  75. end
  76. end
  77. end
  78. protected
  79. def load_entries_changesets(entries)
  80. return unless entries
  81. entries_with_identifier =
  82. entries.select {|entry| entry.lastrev && entry.lastrev.identifier.present?}
  83. identifiers = entries_with_identifier.map {|entry| entry.lastrev.identifier}.compact.uniq
  84. if identifiers.any?
  85. changesets_by_identifier =
  86. changesets.where(:revision => identifiers).
  87. includes(:user, :repository).group_by(&:revision)
  88. entries_with_identifier.each do |entry|
  89. if m = changesets_by_identifier[entry.lastrev.identifier]
  90. entry.changeset = m.first
  91. end
  92. end
  93. end
  94. end
  95. private
  96. # Returns the relative url of the repository
  97. # Eg: root_url = file:///var/svn/foo
  98. # url = file:///var/svn/foo/bar
  99. # => returns /bar
  100. def relative_url
  101. @relative_url ||= url.gsub(Regexp.new("^#{Regexp.escape(root_url || scm.root_url)}", Regexp::IGNORECASE), '')
  102. end
  103. end