mirror of
https://github.com/meineerde/redmine.git
synced 2026-03-11 19:53:07 +00:00
misc scm browser improvements
git-svn-id: http://redmine.rubyforge.org/svn/branches/work@103 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
9db7b56f4d
commit
efe31d49f0
@ -6,30 +6,31 @@ class RepositoriesController < ApplicationController
|
||||
end
|
||||
|
||||
def browse
|
||||
@rev = params[:rev].to_i if params[:rev] and params[:rev].to_i > 0
|
||||
@entries = @repository.scm.entries(@path, @rev)
|
||||
redirect_to :action => 'show', :id => @project and return unless @entries
|
||||
end
|
||||
|
||||
def entry_revisions
|
||||
@entry = @repository.scm.entry(@path, @rev)
|
||||
redirect_to :action => 'show', :id => @project and return unless @entry
|
||||
if @entry.is_dir?
|
||||
# if entry is a dir, shows directory listing
|
||||
@entries = @repository.scm.entries(@path, @rev)
|
||||
redirect_to :action => 'show', :id => @project and return unless @entries
|
||||
else
|
||||
# else, shows file's revisions
|
||||
@revisions = @repository.scm.revisions(@path, @rev)
|
||||
redirect_to :action => 'show', :id => @project and return unless @revisions
|
||||
render :action => 'entry_revisions'
|
||||
@revisions = @repository.scm.revisions(@path, @rev)
|
||||
redirect_to :action => 'show', :id => @project and return unless @entry && @revisions
|
||||
end
|
||||
|
||||
def entry
|
||||
if 'raw' == params[:format]
|
||||
content = @repository.scm.cat(@path, @rev)
|
||||
redirect_to :action => 'show', :id => @project and return unless content
|
||||
send_data content, :filename => @path.split('/').last
|
||||
end
|
||||
end
|
||||
|
||||
def revision
|
||||
@rev = params[:rev].to_i if params[:rev] and params[:rev].to_i > 0
|
||||
@revisions = @repository.scm.revisions '', @rev, @rev, :with_paths => true
|
||||
redirect_to :action => 'show', :id => @project and return unless @revisions
|
||||
@revision = @revisions.first
|
||||
end
|
||||
|
||||
def diff
|
||||
@rev = params[:rev].to_i if params[:rev] and params[:rev].to_i > 0
|
||||
@rev_to = params[:rev_to] || (@rev-1)
|
||||
@diff = @repository.scm.diff(params[:path], @rev, @rev_to)
|
||||
redirect_to :action => 'show', :id => @project and return unless @diff
|
||||
@ -40,5 +41,7 @@ private
|
||||
@project = Project.find(params[:id])
|
||||
@repository = @project.repository
|
||||
@path = params[:path].squeeze('/').gsub(/^\//, '') if params[:path]
|
||||
@path ||= ''
|
||||
@rev = params[:rev].to_i if params[:rev] and params[:rev].to_i > 0
|
||||
end
|
||||
end
|
||||
|
||||
@ -9,7 +9,7 @@ module SvnRepos
|
||||
@url = nil
|
||||
@login = nil
|
||||
@password = nil
|
||||
|
||||
|
||||
def initialize(url, login=nil, password=nil)
|
||||
@url = url
|
||||
@login = login if login && !login.empty?
|
||||
@ -19,31 +19,8 @@ module SvnRepos
|
||||
# Returns the entry identified by path and revision identifier
|
||||
# or nil if entry doesn't exist in the repository
|
||||
def entry(path=nil, identifier=nil)
|
||||
path ||= ''
|
||||
identifier = 'HEAD' unless identifier and identifier > 0
|
||||
entry = nil
|
||||
cmd = "svn info --xml -r #{identifier} #{target(path)}"
|
||||
IO.popen(cmd) do |io|
|
||||
begin
|
||||
doc = REXML::Document.new(io)
|
||||
doc.elements.each("info/entry") do |info|
|
||||
entry = Entry.new({:name => info.attributes['path'],
|
||||
:path => path,
|
||||
:kind => info.attributes['kind'],
|
||||
:lastrev => Revision.new({
|
||||
:identifier => info.elements['commit'].attributes['revision'],
|
||||
:author => info.elements['commit'].elements['author'].text,
|
||||
:time => Time.parse(info.elements['commit'].elements['date'].text)
|
||||
})
|
||||
})
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
return nil if $? && $?.exitstatus != 0
|
||||
entry
|
||||
rescue Errno::ENOENT
|
||||
raise RepositoryCmdFailed
|
||||
e = entries(path, identifier)
|
||||
e ? e.first : nil
|
||||
end
|
||||
|
||||
# Returns an Entries collection
|
||||
@ -52,8 +29,8 @@ module SvnRepos
|
||||
path ||= ''
|
||||
identifier = 'HEAD' unless identifier and identifier > 0
|
||||
entries = Entries.new
|
||||
cmd = "svn list --xml -r #{identifier} #{target(path)}"
|
||||
IO.popen(cmd) do |io|
|
||||
cmd = "svn list --xml #{target(path)}@#{identifier}"
|
||||
shellout(cmd) do |io|
|
||||
begin
|
||||
doc = REXML::Document.new(io)
|
||||
doc.elements.each("lists/list/entry") do |entry|
|
||||
@ -85,7 +62,7 @@ module SvnRepos
|
||||
cmd = "svn log --xml -r #{identifier_from}:#{identifier_to} "
|
||||
cmd << "--verbose " if options[:with_paths]
|
||||
cmd << target(path)
|
||||
IO.popen(cmd) do |io|
|
||||
shellout(cmd) do |io|
|
||||
begin
|
||||
doc = REXML::Document.new(io)
|
||||
doc.elements.each("log/logentry") do |logentry|
|
||||
@ -95,6 +72,8 @@ module SvnRepos
|
||||
:path => path.text
|
||||
}
|
||||
end
|
||||
paths.sort! { |x,y| x[:path] <=> y[:path] }
|
||||
|
||||
revisions << Revision.new({:identifier => logentry.attributes['revision'],
|
||||
:author => logentry.elements['author'].text,
|
||||
:time => Time.parse(logentry.elements['date'].text),
|
||||
@ -121,9 +100,9 @@ module SvnRepos
|
||||
cmd = "svn diff -r "
|
||||
cmd << "#{identifier_to}:"
|
||||
cmd << "#{identifier_from}"
|
||||
cmd << target(path)
|
||||
cmd << "#{target(path)}@#{identifier_from}"
|
||||
diff = []
|
||||
IO.popen(cmd) do |io|
|
||||
shellout(cmd) do |io|
|
||||
io.each_line do |line|
|
||||
diff << line
|
||||
end
|
||||
@ -133,11 +112,35 @@ module SvnRepos
|
||||
rescue Errno::ENOENT => e
|
||||
raise CommandFailed
|
||||
end
|
||||
|
||||
def cat(path, identifier=nil)
|
||||
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
|
||||
cmd = "svn cat #{target(path)}@#{identifier}"
|
||||
cat = nil
|
||||
shellout(cmd) do |io|
|
||||
cat = io.read
|
||||
end
|
||||
return nil if $? && $?.exitstatus != 0
|
||||
cat
|
||||
rescue Errno::ENOENT => e
|
||||
raise CommandFailed
|
||||
end
|
||||
|
||||
private
|
||||
def target(path)
|
||||
" \"" << "#{@url}/#{path}".gsub(/["'<>]/, '') << "\""
|
||||
end
|
||||
|
||||
def logger
|
||||
RAILS_DEFAULT_LOGGER
|
||||
end
|
||||
|
||||
def shellout(cmd, &block)
|
||||
logger.debug "Shelling out: #{cmd}" if logger && logger.debug?
|
||||
IO.popen(cmd) do |io|
|
||||
block.call(io) if block_given?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Entries < Array
|
||||
|
||||
@ -1,9 +1,18 @@
|
||||
<%= link_to 'root', :action => 'browse', :id => @project, :path => '', :rev => @rev %>
|
||||
<% link_path = ''
|
||||
path.split('/').each do |dir|
|
||||
<%
|
||||
dirs = path.split('/')
|
||||
if 'file' == kind
|
||||
filename = dirs.pop
|
||||
end
|
||||
link_path = ''
|
||||
dirs.each do |dir|
|
||||
link_path << '/' unless link_path.empty?
|
||||
link_path << "#{dir}"
|
||||
%>
|
||||
/ <%= link_to h(dir), :action => 'browse', :id => @project, :path => link_path, :rev => @rev %>
|
||||
<% end %>
|
||||
<% if filename %>
|
||||
/ <%= link_to h(filename), :action => 'entry_revisions', :id => @project, :path => "#{link_path}/#{filename}", :rev => @rev %>
|
||||
<% end %>
|
||||
|
||||
<%= "@ #{revision}" if revision %>
|
||||
@ -6,7 +6,7 @@
|
||||
<%= submit_tag 'OK' %>
|
||||
</div>
|
||||
|
||||
<h2><%= render :partial => 'navigation', :locals => { :path => @entry.path, :revision => @rev } %></h2>
|
||||
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'dir', :revision => @rev } %></h2>
|
||||
|
||||
<table class="list">
|
||||
<thead><tr>
|
||||
@ -20,7 +20,7 @@
|
||||
<% total_size = 0
|
||||
@entries.each do |entry| %>
|
||||
<tr class="<%= cycle 'odd', 'even' %>">
|
||||
<td><%= link_to h(entry.name), { :action => 'browse', :id => @project, :path => entry.path, :rev => @rev }, :class => "icon " + (entry.is_dir? ? 'folder' : 'file') %></td>
|
||||
<td><%= link_to h(entry.name), { :action => (entry.is_dir? ? 'browse' : 'entry_revisions'), :id => @project, :path => entry.path, :rev => @rev }, :class => "icon " + (entry.is_dir? ? 'folder' : 'file') %></td>
|
||||
<td align="right"><%= human_size(entry.size) unless entry.is_dir? %></td>
|
||||
<td align="right"><%= link_to entry.lastrev.identifier, :action => 'revision', :id => @project, :rev => entry.lastrev.identifier %></td>
|
||||
<td align="center"><em><%=h entry.lastrev.author %></em></td>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :revision => @rev } %></h2>
|
||||
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2>
|
||||
|
||||
<%= stylesheet_link_tag "scm" %>
|
||||
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
<%= submit_tag 'OK' %>
|
||||
</div>
|
||||
|
||||
<h2><%= render :partial => 'navigation', :locals => { :path => @entry.path, :revision => @rev } %></h2>
|
||||
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => @entry.kind, :revision => @rev } %></h2>
|
||||
|
||||
<h3><%=h @entry.name %></h3>
|
||||
<p><%= link_to 'Download', {}, :class => "icon file" %></p>
|
||||
<p><%= link_to 'Download', {:action => 'entry', :id => @project, :path => @path, :rev => @rev, :format => 'raw' }, :class => "icon file" %> (<%= human_size @entry.size %>)</p>
|
||||
|
||||
<h3>Revisions</h3>
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
<td align="center"><em><%=h revision.author %></em></td>
|
||||
<td align="center"><%= format_time(revision.time) %></td>
|
||||
<td width="70%"><%= simple_format(h(revision.message)) %></td>
|
||||
<td><%= link_to 'View diff', :action => 'diff', :id => @project, :path => @entry.path, :rev => revision.identifier %></td>
|
||||
<td align="center"><%= link_to 'Diff', :action => 'diff', :id => @project, :path => @path, :rev => revision.identifier unless revision == @revisions.last %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
|
||||
@ -8,9 +8,15 @@
|
||||
|
||||
<h2><%= l(:label_revision) %> <%= @revision.identifier %></h2>
|
||||
|
||||
<p><%= l(:field_author) %>: <em><%= @revision.author %></em></p>
|
||||
<p><em><%= @revision.author %>, <%= format_time(@revision.time) %></em></p>
|
||||
<%= simple_format @revision.message %>
|
||||
|
||||
<div style="float:right;">
|
||||
<div class="square action_A"></div> <div style="float:left;"><%= l(:label_added) %> </div>
|
||||
<div class="square action_M"></div> <div style="float:left;"><%= l(:label_modified) %> </div>
|
||||
<div class="square action_D"></div> <div style="float:left;"><%= l(:label_deleted) %> </div>
|
||||
</div>
|
||||
|
||||
<h3><%= l(:label_attachment_plural) %></h3>
|
||||
<table class="list">
|
||||
<tbody>
|
||||
|
||||
@ -289,6 +289,9 @@ label_browse: Parcourir
|
||||
label_modification: %d modification
|
||||
label_modification_plural: %d modifications
|
||||
label_revision: Révision
|
||||
label_added: ajouté
|
||||
label_modified: modifié
|
||||
label_deleted: supprimé
|
||||
|
||||
button_login: Connexion
|
||||
button_submit: Soumettre
|
||||
|
||||
@ -29,6 +29,7 @@ table.list tbody th {
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
background: #eed;
|
||||
border: 1px solid #d7d7d7;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@ -42,7 +43,7 @@ table.list tbody th {
|
||||
|
||||
|
||||
|
||||
table.diff tr.spacing {
|
||||
tr.spacing {
|
||||
border: 1px solid #d7d7d7;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user