Commit 3c20a9b0 authored by Jean-Philippe Lang's avatar Jean-Philippe Lang

Do not parse the entire git log to fetch new commits (takes several minutes for…

Do not parse the entire git log to fetch new commits (takes several minutes for a few thousands commits), but only 1 week before the last known commit (#4547, #4716).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3394 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent be2004e3
......@@ -40,23 +40,26 @@ class Repository::Git < Repository
# With SCM's that have a sequential commit numbering, redmine is able to be
# clever and only fetch changesets going forward from the most recent one
# it knows about. However, with git, you never know if people have merged
# commits into the middle of the repository history, so we always have to
# parse the entire log.
# commits into the middle of the repository history, so we should parse
# the entire log. Since it's way too slow for large repositories, we only
# parse 1 week before the last known commit.
# The repository can still be fully reloaded by calling #clear_changesets
# before fetching changesets (eg. for offline resync)
def fetch_changesets
# Save ourselves an expensive operation if we're already up to date
return if scm.num_revisions == changesets.count
c = changesets.find(:first, :order => 'committed_on DESC')
since = (c ? c.committed_on - 7.days : nil)
revisions = scm.revisions('', nil, nil, :all => true)
revisions = scm.revisions('', nil, nil, :all => true, :since => since)
return if revisions.nil? || revisions.empty?
# Find revisions that redmine knows about already
existing_revisions = changesets.find(:all).map!{|c| c.scmid}
recent_changesets = changesets.find(:all, :conditions => ['committed_on >= ?', since])
# Clean out revisions that are no longer in git
Changeset.delete_all(["scmid NOT IN (?) AND repository_id = (?)", revisions.map{|r| r.scmid}, self.id])
recent_changesets.each {|c| c.destroy unless revisions.detect {|r| r.scmid.to_s == c.scmid.to_s }}
# Subtract revisions that redmine already knows about
revisions.reject!{|r| existing_revisions.include?(r.scmid)}
recent_revisions = recent_changesets.map{|c| c.scmid}
revisions.reject!{|r| recent_revisions.include?(r.scmid)}
# Save the remaining ones to the database
revisions.each{|r| r.save(self)} unless revisions.nil?
......
......@@ -110,11 +110,6 @@ module Redmine
end
end
def num_revisions
cmd = "#{GIT_BIN} --git-dir #{target('')} log --all --pretty=format:'' | wc -l"
shellout(cmd) {|io| io.gets.chomp.to_i + 1}
end
def revisions(path, identifier_from, identifier_to, options={})
revisions = Revisions.new
......@@ -124,6 +119,7 @@ module Redmine
cmd << " -n #{options[:limit]} " if options[:limit]
cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from
cmd << " #{shell_quote identifier_to} " if identifier_to
cmd << " --since=#{shell_quote(options[:since].strftime("%Y-%m-%d %H:%M:%S"))}" if options[:since]
cmd << " -- #{path}" if path && !path.empty?
shellout(cmd) do |io|
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment