summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects_controller.rb22
-rw-r--r--app/controllers/repositories_controller.rb24
-rw-r--r--app/models/change.rb22
-rw-r--r--app/models/changeset.rb25
-rw-r--r--app/models/repository.rb60
-rw-r--r--app/models/svn_repos.rb42
-rw-r--r--app/views/projects/_form.rhtml2
-rw-r--r--app/views/projects/activity.rhtml4
-rw-r--r--app/views/projects/search.rhtml7
-rw-r--r--app/views/repositories/_revisions.rhtml20
-rw-r--r--app/views/repositories/revision.rhtml16
-rw-r--r--app/views/repositories/revisions.rhtml27
-rw-r--r--app/views/repositories/show.rhtml15
-rw-r--r--app/views/settings/edit.rhtml3
-rw-r--r--config/settings.yml2
-rw-r--r--db/migrate/034_create_changesets.rb16
-rw-r--r--db/migrate/035_create_changes.rb16
-rw-r--r--lang/de.yml2
-rw-r--r--lang/en.yml2
-rw-r--r--lang/es.yml2
-rw-r--r--lang/fr.yml2
-rw-r--r--lang/it.yml2
-rw-r--r--lang/ja.yml2
23 files changed, 267 insertions, 68 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 129355851..410e24847 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -519,6 +519,17 @@ class ProjectsController < ApplicationController
@show_wiki_edits = 1
end
+ unless @project.repository.nil? || params[:show_changesets] == "0"
+ @project.repository.changesets.find(:all, :conditions => ["#{Changeset.table_name}.committed_on BETWEEN ? AND ?", @date_from, @date_to]).each { |i|
+ def i.created_on
+ self.committed_on
+ end
+ @events_by_day[i.created_on.to_date] ||= []
+ @events_by_day[i.created_on.to_date] << i
+ }
+ @show_changesets = 1
+ end
+
render :layout => false if request.xhr?
end
@@ -581,10 +592,10 @@ class ProjectsController < ApplicationController
@question = params[:q] || ""
@question.strip!
@all_words = params[:all_words] || (params[:submit] ? false : true)
- @scope = params[:scope] || (params[:submit] ? [] : %w(issues news documents wiki) )
- if !@question.empty?
- # tokens must be at least 3 character long
- @tokens = @question.split.uniq.select {|w| w.length > 2 }
+ @scope = params[:scope] || (params[:submit] ? [] : %w(issues changesets news documents wiki) )
+ # tokens must be at least 3 character long
+ @tokens = @question.split.uniq.select {|w| w.length > 2 }
+ if !@tokens.empty?
# no more than 5 tokens to search for
@tokens.slice! 5..-1 if @tokens.size > 5
# strings used in sql like statement
@@ -596,7 +607,10 @@ class ProjectsController < ApplicationController
@results += @project.news.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort], :include => :author ) if @scope.include? 'news'
@results += @project.documents.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'documents'
@results += @project.wiki.pages.find(:all, :limit => limit, :include => :content, :conditions => [ (["(LOWER(title) like ? OR LOWER(text) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @project.wiki && @scope.include?('wiki')
+ @results += @project.repository.changesets.find(:all, :limit => limit, :conditions => [ (["(LOWER(comment) like ?)"] * like_tokens.size).join(operator), * (like_tokens).sort] ) if @project.repository && @scope.include?('changesets')
@question = @tokens.join(" ")
+ else
+ @question = ""
end
end
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index acf03eb7b..94b81080f 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -1,5 +1,5 @@
# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -20,9 +20,16 @@ class RepositoriesController < ApplicationController
before_filter :find_project, :authorize
def show
+ # get entries for the browse frame
@entries = @repository.scm.entries('')
show_error and return unless @entries
- @latest_revision = @entries.revisions.latest
+ # check if new revisions have been committed in the repository
+ scm_latestrev = @entries.revisions.latest
+ if Setting.autofetch_changesets? && scm_latestrev && ((@repository.latest_changeset.nil?) || (@repository.latest_changeset.revision < scm_latestrev.identifier.to_i))
+ @repository.fetch_changesets
+ @repository.reload
+ end
+ @changesets = @repository.changesets.find(:all, :limit => 5, :order => "committed_on DESC")
end
def browse
@@ -31,9 +38,11 @@ class RepositoriesController < ApplicationController
end
def revisions
- @entry = @repository.scm.entry(@path, @rev)
- @revisions = @repository.scm.revisions(@path, @rev)
- show_error and return unless @entry && @revisions
+ unless @path == ''
+ @entry = @repository.scm.entry(@path, @rev)
+ show_error and return unless @entry
+ end
+ @changesets = @repository.changesets_for_path(@path)
end
def entry
@@ -45,9 +54,8 @@ class RepositoriesController < ApplicationController
end
def revision
- @revisions = @repository.scm.revisions '', @rev, @rev, :with_paths => true
- show_error and return unless @revisions
- @revision = @revisions.first
+ @changeset = @repository.changesets.find_by_revision(@rev)
+ show_error and return unless @changeset
end
def diff
diff --git a/app/models/change.rb b/app/models/change.rb
new file mode 100644
index 000000000..d14f435a4
--- /dev/null
+++ b/app/models/change.rb
@@ -0,0 +1,22 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class Change < ActiveRecord::Base
+ belongs_to :changeset
+
+ validates_presence_of :changeset_id, :action, :path
+end
diff --git a/app/models/changeset.rb b/app/models/changeset.rb
new file mode 100644
index 000000000..fa60f1db8
--- /dev/null
+++ b/app/models/changeset.rb
@@ -0,0 +1,25 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class Changeset < ActiveRecord::Base
+ belongs_to :repository
+ has_many :changes, :dependent => :delete_all
+
+ validates_presence_of :repository_id, :revision, :committed_on
+ validates_numericality_of :revision, :only_integer => true
+ validates_uniqueness_of :revision, :scope => :repository_id
+end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 16bee25a7..19b12f372 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1,5 +1,5 @@
# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -17,6 +17,11 @@
class Repository < ActiveRecord::Base
belongs_to :project
+ has_many :changesets, :dependent => :destroy, :order => 'revision DESC'
+ 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
@@ -27,10 +32,55 @@ class Repository < ActiveRecord::Base
end
def url=(str)
- unless str == self.url
- self.attributes = {:root_url => nil }
- @scm = nil
+ super if root_url.blank?
+ end
+
+ def changesets_for_path(path="")
+ path = "/#{path}%"
+ path = url.gsub(/^#{root_url}/, '') + path if root_url && root_url != url
+ path.squeeze!("/")
+ changesets.find(:all, :include => :changes,
+ :conditions => ["#{Change.table_name}.path LIKE ?", path])
+ 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,
+ :comment => 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
+ identifier_from = identifier_to + 1
+ end
+ end
end
- super
+ end
+
+ # fetch new changesets for all repositories
+ # can be called periodically by an external script
+ # eg. ruby script/runner "Repository.fetch_changesets"
+ def self.fetch_changesets
+ find(:all).each(&:fetch_changesets)
end
end
diff --git a/app/models/svn_repos.rb b/app/models/svn_repos.rb
index 2fd907319..610b67a20 100644
--- a/app/models/svn_repos.rb
+++ b/app/models/svn_repos.rb
@@ -1,5 +1,5 @@
# redMine - project management software
-# Copyright (C) 2006 Jean-Philippe Lang
+# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -39,20 +39,27 @@ module SvnRepos
@url
end
- # finds the root url of the svn repository
- def retrieve_root_url
+ # get info about the svn repository
+ def info
cmd = "svn info --xml #{target('')}"
cmd << " --username #{@login} --password #{@password}" if @login
- root_url = nil
+ info = nil
shellout(cmd) do |io|
begin
doc = REXML::Document.new(io)
- root_url = doc.elements["info/entry/repository/root"].text
+ #root_url = doc.elements["info/entry/repository/root"].text
+ info = Info.new({:root_url => doc.elements["info/entry/repository/root"].text,
+ :lastrev => Revision.new({
+ :identifier => doc.elements["info/entry/commit"].attributes['revision'],
+ :time => Time.parse(doc.elements["info/entry/commit/date"].text),
+ :author => (doc.elements["info/entry/commit/author"] ? doc.elements["info/entry/commit/author"].text : "")
+ })
+ })
rescue
end
end
return nil if $? && $?.exitstatus != 0
- root_url
+ info
rescue Errno::ENOENT => e
return nil
end
@@ -83,7 +90,7 @@ module SvnRepos
:lastrev => Revision.new({
:identifier => entry.elements['commit'].attributes['revision'],
:time => Time.parse(entry.elements['commit'].elements['date'].text),
- :author => (entry.elements['commit'].elements['author'] ? entry.elements['commit'].elements['author'].text : "anonymous")
+ :author => (entry.elements['commit'].elements['author'] ? entry.elements['commit'].elements['author'].text : "")
})
})
end
@@ -112,13 +119,15 @@ module SvnRepos
paths = []
logentry.elements.each("paths/path") do |path|
paths << {:action => path.attributes['action'],
- :path => path.text
+ :path => path.text,
+ :from_path => path.attributes['copyfrom-path'],
+ :from_revision => path.attributes['copyfrom-rev']
}
end
paths.sort! { |x,y| x[:path] <=> y[:path] }
revisions << Revision.new({:identifier => logentry.attributes['revision'],
- :author => (logentry.elements['author'] ? logentry.elements['author'].text : "anonymous"),
+ :author => (logentry.elements['author'] ? logentry.elements['author'].text : ""),
:time => Time.parse(logentry.elements['date'].text),
:message => logentry.elements['msg'].text,
:paths => paths
@@ -171,7 +180,12 @@ module SvnRepos
raise CommandFailed
end
- private
+ private
+ def retrieve_root_url
+ info = self.info
+ info ? info.root_url : nil
+ end
+
def target(path)
path ||= ""
base = path.match(/^\//) ? root_url : url
@@ -207,6 +221,14 @@ module SvnRepos
end
end
+ class Info
+ attr_accessor :root_url, :lastrev
+ def initialize(attributes={})
+ self.root_url = attributes[:root_url] if attributes[:root_url]
+ self.lastrev = attributes[:lastrev]
+ end
+ end
+
class Entry
attr_accessor :name, :path, :kind, :size, :lastrev
def initialize(attributes={})
diff --git a/app/views/projects/_form.rhtml b/app/views/projects/_form.rhtml
index 85f3f2966..ded227197 100644
--- a/app/views/projects/_form.rhtml
+++ b/app/views/projects/_form.rhtml
@@ -30,7 +30,7 @@
<%= hidden_field_tag "repository_enabled", 0 %>
<div id="repository">
<% fields_for :repository, @project.repository, { :builder => TabularFormBuilder, :lang => current_language} do |repository| %>
-<p><%= repository.text_field :url, :size => 60, :required => true %><br />(http://, https://, svn://, file:///)</p>
+<p><%= repository.text_field :url, :size => 60, :required => true, :disabled => (@project.repository && !@project.repository.root_url.blank?) %><br />(http://, https://, svn://, file:///)</p>
<p><%= repository.text_field :login, :size => 30 %></p>
<p><%= repository.password_field :password, :size => 30 %></p>
<% end %>
diff --git a/app/views/projects/activity.rhtml b/app/views/projects/activity.rhtml
index b1d131aa9..69bfa6028 100644
--- a/app/views/projects/activity.rhtml
+++ b/app/views/projects/activity.rhtml
@@ -7,6 +7,7 @@
<%= select_year(@year, :prefix => "year", :discard_type => true) %></p>
<p>
<%= check_box_tag 'show_issues', 1, @show_issues %><%= hidden_field_tag 'show_issues', 0, :id => nil %> <%=l(:label_issue_plural)%><br />
+ <% if @project.repository %><%= check_box_tag 'show_changesets', 1, @show_changesets %><%= hidden_field_tag 'show_changesets', 0, :id => nil %> <%=l(:label_revision_plural)%><br /><% end %>
<%= check_box_tag 'show_news', 1, @show_news %><%= hidden_field_tag 'show_news', 0, :id => nil %> <%=l(:label_news_plural)%><br />
<%= check_box_tag 'show_files', 1, @show_files %><%= hidden_field_tag 'show_files', 0, :id => nil %> <%=l(:label_attachment_plural)%><br />
<%= check_box_tag 'show_documents', 1, @show_documents %><%= hidden_field_tag 'show_documents', 0, :id => nil %> <%=l(:label_document_plural)%><br />
@@ -39,6 +40,9 @@
<% elsif e.is_a? WikiContent.versioned_class %>
<%= e.created_on.strftime("%H:%M") %> <%=l(:label_wiki_edit)%>: <%= link_to h(WikiPage.pretty_title(e.title)), :controller => 'wiki', :page => e.title %> (<%= link_to '#' + e.version.to_s, :controller => 'wiki', :page => e.title, :version => e.version %>)<br />
<% unless e.comment.blank? %><em><%=h e.comment %></em><% end %>
+ <% elsif e.is_a? Changeset %>
+ <%= e.created_on.strftime("%H:%M") %> <%=l(:label_revision)%> <%= link_to h(e.revision), :controller => 'repositories', :action => 'revision', :id => @project, :rev => e.revision %><br />
+ <em><%=h e.committer %><%= h(": #{e.comment}") unless e.comment.blank? %></em>
<% end %>
</p></li>
diff --git a/app/views/projects/search.rhtml b/app/views/projects/search.rhtml
index 056effd47..8b35dce3b 100644
--- a/app/views/projects/search.rhtml
+++ b/app/views/projects/search.rhtml
@@ -4,6 +4,9 @@
<% form_tag({:action => 'search', :id => @project}, :method => :get) do %>
<p><%= text_field_tag 'q', @question, :size => 30 %>
<%= check_box_tag 'scope[]', 'issues', (@scope.include? 'issues') %> <label><%= l(:label_issue_plural) %></label>
+<% if @project.repository %>
+<%= check_box_tag 'scope[]', 'changesets', (@scope.include? 'changesets') %> <label><%= l(:label_revision_plural) %></label>
+<% end %>
<%= check_box_tag 'scope[]', 'news', (@scope.include? 'news') %> <label><%= l(:label_news_plural) %></label>
<%= check_box_tag 'scope[]', 'documents', (@scope.include? 'documents') %> <label><%= l(:label_document_plural) %></label>
<% if @project.wiki %>
@@ -36,6 +39,10 @@
<%=l(:label_wiki)%>: <%= link_to highlight_tokens(h(e.pretty_title), @tokens), :controller => 'wiki', :action => 'index', :id => @project, :page => e.title %><br />
<%= highlight_tokens(e.content.text, @tokens) %><br />
<i><%= e.content.author ? e.content.author.name : "Anonymous" %>, <%= format_time(e.content.updated_on) %></i>
+ <% elsif e.is_a? Changeset %>
+ <%=l(:label_revision)%> <%= link_to h(e.revision), :controller => 'repositories', :action => 'revision', :id => @project, :rev => e.revision %><br />
+ <%= highlight_tokens(e.comment, @tokens) %><br />
+ <em><%= e.committer.blank? ? e.committer : "Anonymous" %>, <%= format_time(e.committed_on) %></em>
<% end %>
</p></li>
<% end %>
diff --git a/app/views/repositories/_revisions.rhtml b/app/views/repositories/_revisions.rhtml
new file mode 100644
index 000000000..d9bf7cc7c
--- /dev/null
+++ b/app/views/repositories/_revisions.rhtml
@@ -0,0 +1,20 @@
+<table class="list">
+<thead><tr>
+<th>#</th>
+<th><%= l(:field_author) %></th>
+<th><%= l(:label_date) %></th>
+<th><%= l(:field_comment) %></th>
+<th></th>
+</tr></thead>
+<tbody>
+<% changesets.each do |changeset| %>
+<tr class="<%= cycle 'odd', 'even' %>">
+<th align="center"><%= link_to changeset.revision, :action => 'revision', :id => project, :rev => changeset.revision %></th>
+<td align="center"><em><%=h changeset.committer %></em></td>
+<td align="center"><%= format_time(changeset.committed_on) %></td>
+<td style="width:70%"><%= textilizable(changeset.comment) %></td>
+<td align="center"><%= link_to 'Diff', :action => 'diff', :id => project, :path => path, :rev => changeset.revision if entry && entry.is_file? && changeset != changesets.last %></td>
+</tr>
+<% end %>
+</tbody>
+</table> \ No newline at end of file
diff --git a/app/views/repositories/revision.rhtml b/app/views/repositories/revision.rhtml
index 22e965090..3f28f3a9c 100644
--- a/app/views/repositories/revision.rhtml
+++ b/app/views/repositories/revision.rhtml
@@ -5,10 +5,10 @@
<% end %>
</div>
-<h2><%= l(:label_revision) %> <%= @revision.identifier %></h2>
+<h2><%= l(:label_revision) %> <%= @changeset.revision %></h2>
-<p><em><%= @revision.author %>, <%= format_time(@revision.time) %></em></p>
-<%= textilizable @revision.message %>
+<p><em><%= @changeset.committer %>, <%= format_time(@changeset.committed_on) %></em></p>
+<%= textilizable @changeset.comment %>
<div style="float:right;">
<div class="square action_A"></div> <div style="float:left;"><%= l(:label_added) %>&nbsp;</div>
@@ -19,19 +19,19 @@
<h3><%= l(:label_attachment_plural) %></h3>
<table class="list">
<tbody>
-<% @revision.paths.each do |path| %>
+<% @changeset.changes.each do |change| %>
<tr class="<%= cycle 'odd', 'even' %>">
-<td><div class="square action_<%= path[:action] %>"></div> <%= path[:path] %></td>
+<td><div class="square action_<%= change.action %>"></div> <%= change.path %></td>
<td>
-<% if path[:action] == "M" %>
-<%= link_to 'View diff', :action => 'diff', :id => @project, :path => path[:path], :rev => @revision.identifier %>
+<% if change.action == "M" %>
+<%= link_to 'View diff', :action => 'diff', :id => @project, :path => change.path, :rev => @changeset.revision %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
-<p><%= lwr(:label_modification, @revision.paths.length) %></p>
+<p><%= lwr(:label_modification, @changeset.changes.length) %></p>
<% content_for :header_tags do %>
<%= stylesheet_link_tag "scm" %>
diff --git a/app/views/repositories/revisions.rhtml b/app/views/repositories/revisions.rhtml
index 8e300a9da..52564472d 100644
--- a/app/views/repositories/revisions.rhtml
+++ b/app/views/repositories/revisions.rhtml
@@ -5,36 +5,17 @@
<% end %>
</div>
-<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => @entry.kind, :revision => @rev } %></h2>
+<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => (@entry ? @entry.kind : nil), :revision => @rev } %></h2>
-<% if @entry.is_file? %>
+<% if @entry && @entry.is_file? %>
<h3><%=h @entry.name %></h3>
<p><%= link_to 'Download', {:action => 'entry', :id => @project, :path => @path, :rev => @rev, :format => 'raw' }, :class => "icon file" %> (<%= number_to_human_size @entry.size %>)</p>
<% end %>
<h3>Revisions</h3>
-<table class="list">
-<thead><tr>
-<th>#</th>
-<th><%= l(:field_author) %></th>
-<th><%= l(:label_date) %></th>
-<th><%= l(:field_description) %></th>
-<th></th>
-</tr></thead>
-<tbody>
-<% @revisions.each do |revision| %>
-<tr class="<%= cycle 'odd', 'even' %>">
-<th align="center"><%= link_to revision.identifier, :action => 'revision', :id => @project, :rev => revision.identifier %></th>
-<td align="center"><em><%=h revision.author %></em></td>
-<td align="center"><%= format_time(revision.time) %></td>
-<td style="width:70%"><%= textilizable(revision.message) %></td>
-<td align="center"><%= link_to 'Diff', :action => 'diff', :id => @project, :path => @path, :rev => revision.identifier if @entry.is_file? && revision != @revisions.last %></td>
-</tr>
-<% end %>
-</tbody>
-</table>
-<p><%= lwr(:label_modification, @revisions.length) %></p>
+<%= render :partial => 'revisions', :locals => {:project => @project, :path => @path, :changesets => @changesets, :entry => @entry }%>
+<p><%= lwr(:label_modification, @changesets.length) %></p>
<% content_for :header_tags do %>
<%= stylesheet_link_tag "scm" %>
diff --git a/app/views/repositories/show.rhtml b/app/views/repositories/show.rhtml
index 9c2adc929..e7d71cb79 100644
--- a/app/views/repositories/show.rhtml
+++ b/app/views/repositories/show.rhtml
@@ -1,17 +1,14 @@
<h2><%= l(:label_repository) %></h2>
-<h3><%= l(:label_revision_plural) %></h3>
-<% if @latest_revision %>
- <p><%= l(:label_latest_revision) %>:
- <%= link_to @latest_revision.identifier, :action => 'revision', :id => @project, :rev => @latest_revision.identifier %><br />
- <em><%= @latest_revision.author %>, <%= format_time(@latest_revision.time) %></em></p>
-<% end %>
-<p><%= link_to l(:label_view_revisions), :action => 'revisions', :id => @project %></p>
-
-
<h3><%= l(:label_browse) %></h3>
<%= render :partial => 'dir_list' %>
+<% unless @changesets.empty? %>
+<h3><%= l(:label_latest_revision_plural) %></h3>
+<%= render :partial => 'revisions', :locals => {:project => @project, :path => '', :changesets => @changesets, :entry => nil }%>
+<p><%= link_to l(:label_view_revisions), :action => 'revisions', :id => @project %></p>
+<% end %>
+
<% content_for :header_tags do %>
<%= stylesheet_link_tag "scm" %>
<% end %> \ No newline at end of file
diff --git a/app/views/settings/edit.rhtml b/app/views/settings/edit.rhtml
index 4bdea07b9..223df7a9d 100644
--- a/app/views/settings/edit.rhtml
+++ b/app/views/settings/edit.rhtml
@@ -45,6 +45,9 @@
<p><label><%= l(:setting_feeds_limit) %></label>
<%= text_field_tag 'settings[feeds_limit]', Setting.feeds_limit, :size => 6 %></p>
+<p><label><%= l(:setting_autofetch_changesets) %></label>
+<%= check_box_tag 'settings[autofetch_changesets]', 1, Setting.autofetch_changesets? %><%= hidden_field_tag 'settings[autofetch_changesets]', 0 %></p>
+
</div>
<%= submit_tag l(:button_save) %>
</div>
diff --git a/config/settings.yml b/config/settings.yml
index c3292e516..5942f499b 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -50,3 +50,5 @@ host_name:
feeds_limit:
format: int
default: 15
+autofetch_changesets:
+ default: 1
diff --git a/db/migrate/034_create_changesets.rb b/db/migrate/034_create_changesets.rb
new file mode 100644
index 000000000..a78c8e36f
--- /dev/null
+++ b/db/migrate/034_create_changesets.rb
@@ -0,0 +1,16 @@
+class CreateChangesets < ActiveRecord::Migration
+ def self.up
+ create_table :changesets do |t|
+ t.column :repository_id, :integer, :null => false
+ t.column :revision, :integer, :null => false
+ t.column :committer, :string, :limit => 30
+ t.column :committed_on, :datetime, :null => false
+ t.column :comment, :text
+ end
+ add_index :changesets, [:repository_id, :revision], :unique => true, :name => :changesets_repos_rev
+ end
+
+ def self.down
+ drop_table :changesets
+ end
+end
diff --git a/db/migrate/035_create_changes.rb b/db/migrate/035_create_changes.rb
new file mode 100644
index 000000000..fa0cfac3f
--- /dev/null
+++ b/db/migrate/035_create_changes.rb
@@ -0,0 +1,16 @@
+class CreateChanges < ActiveRecord::Migration
+ def self.up
+ create_table :changes do |t|
+ t.column :changeset_id, :integer, :null => false
+ t.column :action, :string, :limit => 1, :default => "", :null => false
+ t.column :path, :string, :default => "", :null => false
+ t.column :from_path, :string
+ t.column :from_revision, :integer
+ end
+ add_index :changes, [:changeset_id], :name => :changesets_changeset_id
+ end
+
+ def self.down
+ drop_table :changes
+ end
+end
diff --git a/lang/de.yml b/lang/de.yml
index 9bd293559..3046dceb6 100644
--- a/lang/de.yml
+++ b/lang/de.yml
@@ -160,6 +160,7 @@ setting_host_name: Host Name
setting_text_formatting: Textformatierung
setting_wiki_compression: Wiki Historie komprimieren
setting_feeds_limit: Limit Feed Inhalt
+setting_autofetch_changesets: Autofetch SVN commits
label_user: Benutzer
label_user_plural: Benutzer
@@ -315,6 +316,7 @@ label_added: hinzugefügt
label_modified: geändert
label_deleted: gelöscht
label_latest_revision: Aktuelleste Revision
+label_latest_revision_plural: Aktuelleste Revisionen
label_view_revisions: Revisionen anzeigen
label_max_size: Maximale Größe
label_on: von
diff --git a/lang/en.yml b/lang/en.yml
index 72f75597b..6ed10aa88 100644
--- a/lang/en.yml
+++ b/lang/en.yml
@@ -160,6 +160,7 @@ setting_host_name: Host name
setting_text_formatting: Text formatting
setting_wiki_compression: Wiki history compression
setting_feeds_limit: Feed content limit
+setting_autofetch_changesets: Autofetch SVN commits
label_user: User
label_user_plural: Users
@@ -315,6 +316,7 @@ label_added: added
label_modified: modified
label_deleted: deleted
label_latest_revision: Latest revision
+label_latest_revision_plural: Latest revisions
label_view_revisions: View revisions
label_max_size: Maximum size
label_on: 'on'
diff --git a/lang/es.yml b/lang/es.yml
index a8eb1d0d3..a0a04562e 100644
--- a/lang/es.yml
+++ b/lang/es.yml
@@ -160,6 +160,7 @@ setting_host_name: Nombre de anfitrión
setting_text_formatting: Formato de texto
setting_wiki_compression: Compresión de la historia de Wiki
setting_feeds_limit: Feed content limit
+setting_autofetch_changesets: Autofetch SVN commits
label_user: Usuario
label_user_plural: Usuarios
@@ -315,6 +316,7 @@ label_added: agregado
label_modified: modificado
label_deleted: suprimido
label_latest_revision: La revisión más última
+label_latest_revision_plural: Latest revisions
label_view_revisions: Ver las revisiones
label_max_size: Tamaño máximo
label_on: en
diff --git a/lang/fr.yml b/lang/fr.yml
index dbce4b0c7..9a2195b11 100644
--- a/lang/fr.yml
+++ b/lang/fr.yml
@@ -160,6 +160,7 @@ setting_host_name: Nom d'hôte
setting_text_formatting: Formatage du texte
setting_wiki_compression: Compression historique wiki
setting_feeds_limit: Limite du contenu des flux RSS
+setting_autofetch_changesets: Récupération auto. des commits SVN
label_user: Utilisateur
label_user_plural: Utilisateurs
@@ -315,6 +316,7 @@ label_added: ajouté
label_modified: modifié
label_deleted: supprimé
label_latest_revision: Dernière révision
+label_latest_revision_plural: Dernières révisions
label_view_revisions: Voir les révisions
label_max_size: Taille maximale
label_on: sur
diff --git a/lang/it.yml b/lang/it.yml
index e6316e0dd..df89120ff 100644
--- a/lang/it.yml
+++ b/lang/it.yml
@@ -160,6 +160,7 @@ setting_host_name: Nome host
setting_text_formatting: Formattazione testo
setting_wiki_compression: Compressione di storia di Wiki
setting_feeds_limit: Feed content limit
+setting_autofetch_changesets: Autofetch SVN commits
label_user: Utente
label_user_plural: Utenti
@@ -315,6 +316,7 @@ label_added: aggiunto
label_modified: modificato
label_deleted: eliminato
label_latest_revision: Ultima versione
+label_latest_revision_plural: Latest revisions
label_view_revisions: Mostra versioni
label_max_size: Dimensione massima
label_on: 'on'
diff --git a/lang/ja.yml b/lang/ja.yml
index 83e681c0d..57d3df41b 100644
--- a/lang/ja.yml
+++ b/lang/ja.yml
@@ -161,6 +161,7 @@ setting_host_name: ホスト名
setting_text_formatting: テキストの書式
setting_wiki_compression: Wiki history compression
setting_feeds_limit: Feed content limit
+setting_autofetch_changesets: Autofetch SVN commits
label_user: ユーザ
label_user_plural: ユーザ
@@ -316,6 +317,7 @@ label_added: 追加された
label_modified: 変更された
label_deleted: 削除された
label_latest_revision: 最新リビジョン
+label_latest_revision_plural: Latest revisions
label_view_revisions: リビジョンを見る
label_max_size: 最大サイズ
label_on: 他