From 3ba56db935c1b14611fdf87fe7ef8a7f69e68f61 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Wed, 16 Feb 2011 13:35:52 +0000 Subject: [PATCH] scm: mercurial: rewrite MercurialAdapter#entries to show per-file change log and size (#3421, #4455). Contributed by Yuya Nishihara. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4856 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/repository/mercurial.rb | 23 ---------- lib/redmine/scm/adapters/mercurial_adapter.rb | 45 ++++++++++--------- 2 files changed, 24 insertions(+), 44 deletions(-) diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index d8b92a0e..4ee76f44 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -48,29 +48,6 @@ class Repository::Mercurial < Repository super(cs, cs_to, ' ') end - def entries(path=nil, identifier=nil) - entries=scm.entries(path, identifier) - if entries - entries.each do |entry| - next unless entry.is_file? - # Set the filesize unless browsing a specific revision - if identifier.nil? - full_path = File.join(root_url, entry.path) - entry.size = File.stat(full_path).size if File.file?(full_path) - end - # Search the DB for the entry's last change - change = changes.find(:first, :conditions => ["path = ?", scm.with_leading_slash(entry.path)], :order => "#{Changeset.table_name}.committed_on DESC") - if change - entry.lastrev.identifier = change.changeset.revision - entry.lastrev.name = change.changeset.revision - entry.lastrev.author = change.changeset.committer - entry.lastrev.revision = change.revision - end - end - end - entries - end - # Finds and returns a revision with a number or the beginning of a hash def find_changeset_by_name(name) return nil if name.nil? || name.empty? diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index 93cfcf62..d64e6f8f 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -93,28 +93,31 @@ module Redmine private :summary def entries(path=nil, identifier=nil) - path ||= '' - entries = Entries.new - cmd = "#{self.class.sq_bin} -R #{target('')} --cwd #{target('')} locate" - cmd << " -r #{hgrev(identifier, true)}" - cmd << " " + shell_quote("path:#{path}") unless path.empty? - shellout(cmd) do |io| - io.each_line do |line| - # HG uses antislashs as separator on Windows - line = line.gsub(/\\/, "/") - if path.empty? or e = line.gsub!(%r{^#{with_trailling_slash(path)}},'') - e ||= line - e = e.chomp.split(%r{[\/\\]}) - entries << Entry.new({:name => e.first, - :path => (path.nil? or path.empty? ? e.first : "#{with_trailling_slash(path)}#{e.first}"), - :kind => (e.size > 1 ? 'dir' : 'file'), - :lastrev => Revision.new - }) unless e.empty? || entries.detect{|entry| entry.name == e.first} - end - end + manifest = hg('rhmanifest', '-r', hgrev(identifier), + CGI.escape(without_leading_slash(path.to_s))) do |io| + ActiveSupport::XmlMini.parse(io.read)['rhmanifest']['repository']['manifest'] end - return nil if $? && $?.exitstatus != 0 - entries.sort_by_name + path_prefix = path.blank? ? '' : with_trailling_slash(path) + + entries = Entries.new + as_ary(manifest['dir']).each do |e| + n = CGI.unescape(e['name']) + p = "#{path_prefix}#{n}" + entries << Entry.new(:name => n, :path => p, :kind => 'dir') + end + + as_ary(manifest['file']).each do |e| + n = CGI.unescape(e['name']) + p = "#{path_prefix}#{n}" + lr = Revision.new(:revision => e['revision'], :scmid => e['node'], + :time => Time.at(e['time'].to_i)) + entries << Entry.new(:name => n, :path => p, :kind => 'file', + :size => e['size'].to_i, :lastrev => lr) + end + + entries + rescue HgCommandAborted + nil # means not found end def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})