summaryrefslogtreecommitdiffstats
path: root/app/models/repository.rb
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2007-06-12 20:12:05 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2007-06-12 20:12:05 +0000
commit438161ad1fd37aadbfa3f5a875540730fd6d70c3 (patch)
treeb396b2379835a6f768023cdc0f7042259f560875 /app/models/repository.rb
parent4dddb606a6d24c7f95e52f08e689464ab6f8b5b8 (diff)
downloadredmine-438161ad1fd37aadbfa3f5a875540730fd6d70c3.tar.gz
redmine-438161ad1fd37aadbfa3f5a875540730fd6d70c3.zip
Added basic support for CVS and Mercurial SCMs.
Browsing, changesets fetching and diff viewing are implemented. Only tested with local repositories. Thanks to Ralph Vater for CVS specific code. git-svn-id: http://redmine.rubyforge.org/svn/trunk@559 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app/models/repository.rb')
-rw-r--r--app/models/repository.rb78
1 files changed, 27 insertions, 51 deletions
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 692c446d6..667ef5efc 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -17,70 +17,31 @@
class Repository < ActiveRecord::Base
belongs_to :project
- has_many :changesets, :dependent => :destroy, :order => 'revision DESC'
+ has_many :changesets, :dependent => :destroy, :order => "#{Changeset.table_name}.revision DESC"
has_many :changes, :through => :changesets
- has_one :latest_changeset, :class_name => 'Changeset', :foreign_key => :repository_id, :order => 'revision DESC'
-
- attr_protected :root_url
-
- validates_presence_of :url
- validates_format_of :url, :with => /^(http|https|svn|file):\/\/.+/i
def scm
- @scm ||= SvnRepos::Base.new url, root_url, login, password
+ @scm ||= self.scm_adapter.new url, root_url, login, password
update_attribute(:root_url, @scm.root_url) if root_url.blank?
@scm
end
- def url=(str)
- super if root_url.blank?
+ def scm_name
+ self.class.scm_name
end
- def changesets_with_path(path="")
- path = "/#{path}%"
- path = url.gsub(/^#{root_url}/, '') + path if root_url && root_url != url
- path.squeeze!("/")
- # Custom select and joins is done to allow conditions on changes table without loading associated Change objects
- # Required for changesets with a great number of changes (eg. 100,000)
- Changeset.with_scope(:find => { :select => "DISTINCT #{Changeset.table_name}.*", :joins => "LEFT OUTER JOIN #{Change.table_name} ON #{Change.table_name}.changeset_id = #{Changeset.table_name}.id", :conditions => ["#{Change.table_name}.path LIKE ?", path] }) do
- yield
- end
+ def entries(path=nil, identifier=nil)
+ scm.entries(path, identifier)
end
- def fetch_changesets
- scm_info = scm.info
- if scm_info
- lastrev_identifier = scm_info.lastrev.identifier.to_i
- if latest_changeset.nil? || latest_changeset.revision < lastrev_identifier
- logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
- identifier_from = latest_changeset ? latest_changeset.revision + 1 : 1
- while (identifier_from <= lastrev_identifier)
- # loads changesets by batches of 200
- identifier_to = [identifier_from + 199, lastrev_identifier].min
- revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
- transaction do
- revisions.reverse_each do |revision|
- changeset = Changeset.create(:repository => self,
- :revision => revision.identifier,
- :committer => revision.author,
- :committed_on => revision.time,
- :comments => revision.message)
-
- revision.paths.each do |change|
- Change.create(:changeset => changeset,
- :action => change[:action],
- :path => change[:path],
- :from_path => change[:from_path],
- :from_revision => change[:from_revision])
- end
- end
- end unless revisions.nil?
- identifier_from = identifier_to + 1
- end
- end
- end
+ def diff(path, rev, rev_to, type)
+ scm.diff(path, rev, rev_to, type)
end
+ def latest_changeset
+ @latest_changeset ||= changesets.find(:first)
+ end
+
def scan_changesets_for_issue_ids
self.changesets.each(&:scan_comment_for_issue_ids)
end
@@ -96,4 +57,19 @@ class Repository < ActiveRecord::Base
def self.scan_changesets_for_issue_ids
find(:all).each(&:scan_changesets_for_issue_ids)
end
+
+ def self.scm_name
+ 'Abstract'
+ end
+
+ def self.available_scm
+ subclasses.collect {|klass| [klass.scm_name, klass.name]}
+ end
+
+ def self.factory(klass_name, *args)
+ klass = "Repository::#{klass_name}".constantize
+ klass.new(*args)
+ rescue
+ nil
+ end
end