diff --git a/scm/app/controllers/repositories_controller.rb b/scm/app/controllers/repositories_controller.rb index 75881084d..4660a4f58 100644 --- a/scm/app/controllers/repositories_controller.rb +++ b/scm/app/controllers/repositories_controller.rb @@ -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 diff --git a/scm/app/models/svn_repos.rb b/scm/app/models/svn_repos.rb index 1893374b1..c8d49ddbd 100644 --- a/scm/app/models/svn_repos.rb +++ b/scm/app/models/svn_repos.rb @@ -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 diff --git a/scm/app/views/repositories/_navigation.rhtml b/scm/app/views/repositories/_navigation.rhtml index 906d134c5..f7b25cce1 100644 --- a/scm/app/views/repositories/_navigation.rhtml +++ b/scm/app/views/repositories/_navigation.rhtml @@ -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 %> \ No newline at end of file diff --git a/scm/app/views/repositories/browse.rhtml b/scm/app/views/repositories/browse.rhtml index 1e980436b..ebdd0ceab 100644 --- a/scm/app/views/repositories/browse.rhtml +++ b/scm/app/views/repositories/browse.rhtml @@ -6,7 +6,7 @@ <%= submit_tag 'OK' %> -
| <%= link_to h(entry.name), { :action => 'browse', :id => @project, :path => entry.path, :rev => @rev }, :class => "icon " + (entry.is_dir? ? 'folder' : 'file') %> | +<%= 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') %> | <%= human_size(entry.size) unless entry.is_dir? %> | <%= link_to entry.lastrev.identifier, :action => 'revision', :id => @project, :rev => entry.lastrev.identifier %> | <%=h entry.lastrev.author %> | diff --git a/scm/app/views/repositories/diff.rhtml b/scm/app/views/repositories/diff.rhtml index 001e2e480..d4350cb61 100644 --- a/scm/app/views/repositories/diff.rhtml +++ b/scm/app/views/repositories/diff.rhtml @@ -1,4 +1,4 @@ -<%=h revision.author %> | <%= format_time(revision.time) %> | <%= simple_format(h(revision.message)) %> | -<%= link_to 'View diff', :action => 'diff', :id => @project, :path => @entry.path, :rev => revision.identifier %> | +<%= link_to 'Diff', :action => 'diff', :id => @project, :path => @path, :rev => revision.identifier unless revision == @revisions.last %> |