@ -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?