diff -r 92fbf3063e7b app/controllers/repositories_controller.rb --- a/app/controllers/repositories_controller.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/app/controllers/repositories_controller.rb Mon Dec 08 12:04:28 2008 +0100 @@ -94,13 +94,13 @@ def revisions @changeset_count = @repository.changesets.count @changeset_pages = Paginator.new self, @changeset_count, - per_page_option, - params['page'] + per_page_option, + params['page'] @changesets = @repository.changesets.find(:all, - :limit => @changeset_pages.items_per_page, - :offset => @changeset_pages.current.offset, - :include => :user) - + :limit => @changeset_pages.items_per_page, + :offset => @changeset_pages.current.offset, + :include => :user) + respond_to do |format| format.html { render :layout => false if request.xhr? } format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") } @@ -114,15 +114,34 @@ # If the entry is a dir, show the browser browse and return if @entry.is_dir? - @content = @repository.cat(@path, @rev) - show_error_not_found and return unless @content - if 'raw' == params[:format] || @content.is_binary_data? + content = @repository.cat(@path, @rev) + show_error_not_found and return unless content + if 'raw' == params[:format] || content.is_binary_data? # Force the download if it's a binary file - send_data @content, :filename => @path.split('/').last + headers.update( + #'Content-Type' => options[:type].to_s.strip, + 'Content-Disposition' => "attachment; filename=\"#{@path.split('/').last}\"", + 'Content-Transfer-Encoding' => 'binary' + ) + headers['Content-Length'] = @entry.size unless @entry.size.nil? + headers['Cache-Control'] = 'private' if headers['Cache-Control'] == 'no-cache' + + render( :text => Proc.new { |response, output| + begin + logger.info "Streaming entry #{@path}" unless logger.nil? + len = 4096 + while buf = content.read(len) + output.write(buf) + end + ensure + content.close + end + }) else # Prevent empty lines when displaying a file with Windows style eol - @content.gsub!("\r\n", "\n") - end + @content = content.read.gsub("\r\n", "\n") + content.close + end end def annotate @@ -133,7 +152,7 @@ def revision @changeset = @repository.changesets.find_by_revision(@rev) raise ChangesetNotFound unless @changeset - + respond_to do |format| format.html format.js {render :layout => false} @@ -149,8 +168,8 @@ filename = "changeset_r#{@rev}" filename << "_r#{@rev_to}" if @rev_to send_data @diff.join, :filename => "#{filename}.diff", - :type => 'text/x-patch', - :disposition => 'attachment' + :type => 'text/x-patch', + :disposition => 'attachment' else @diff_type = params[:type] || User.current.pref[:diff_type] || 'inline' @diff_type = 'inline' unless %w(inline sbs).include?(@diff_type) @@ -188,7 +207,7 @@ end end -private + private def find_project @project = Project.find(params[:id]) rescue ActiveRecord::RecordNotFound @@ -211,7 +230,7 @@ rescue InvalidRevisionParam show_error_not_found end - + def show_error_not_found render_error l(:error_scm_not_found) end @@ -228,44 +247,44 @@ commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to]) commits_by_month = [0] * 12 commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last } - + changes_by_day = repository.changes.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to]) changes_by_month = [0] * 12 changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last } - + fields = [] month_names = l(:actionview_datehelper_select_month_names_abbr).split(',') 12.times {|m| fields << month_names[((Date.today.month - 1 - m) % 12)]} - + graph = SVG::Graph::Bar.new( - :height => 300, - :width => 800, - :fields => fields.reverse, - :stack => :side, - :scale_integers => true, - :step_x_labels => 2, - :show_data_values => false, - :graph_title => l(:label_commits_per_month), - :show_graph_title => true - ) + :height => 300, + :width => 800, + :fields => fields.reverse, + :stack => :side, + :scale_integers => true, + :step_x_labels => 2, + :show_data_values => false, + :graph_title => l(:label_commits_per_month), + :show_graph_title => true + ) graph.add_data( - :data => commits_by_month[0..11].reverse, - :title => l(:label_revision_plural) - ) - + :data => commits_by_month[0..11].reverse, + :title => l(:label_revision_plural) + ) + graph.add_data( - :data => changes_by_month[0..11].reverse, - :title => l(:label_change_plural) - ) + :data => changes_by_month[0..11].reverse, + :title => l(:label_change_plural) + ) graph.burn end - + def graph_commits_per_author(repository) commits_by_author = repository.changesets.count(:all, :group => :committer) commits_by_author.sort! {|x, y| x.last <=> y.last} - + changes_by_author = repository.changes.count(:all, :group => :committer) h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o} @@ -281,37 +300,37 @@ fields = fields.collect {|c| c.gsub(%r{<.+@.+>}, '') } graph = SVG::Graph::BarHorizontal.new( - :height => 400, - :width => 800, - :fields => fields, - :stack => :side, - :scale_integers => true, - :show_data_values => false, - :rotate_y_labels => false, - :graph_title => l(:label_commits_per_author), - :show_graph_title => true - ) + :height => 400, + :width => 800, + :fields => fields, + :stack => :side, + :scale_integers => true, + :show_data_values => false, + :rotate_y_labels => false, + :graph_title => l(:label_commits_per_author), + :show_graph_title => true + ) graph.add_data( - :data => commits_data, - :title => l(:label_revision_plural) - ) - + :data => commits_data, + :title => l(:label_revision_plural) + ) + graph.add_data( - :data => changes_data, - :title => l(:label_change_plural) - ) - + :data => changes_data, + :title => l(:label_change_plural) + ) + graph.burn end + +end -end - class Date def months_ago(date = Date.today) (date.year - self.year)*12 + (date.month - self.month) end - + def weeks_ago(date = Date.today) (date.year - self.year)*52 + (date.cweek - self.cweek) end diff -r 92fbf3063e7b app/models/repository.rb --- a/app/models/repository.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/app/models/repository.rb Mon Dec 08 12:04:28 2008 +0100 @@ -67,8 +67,8 @@ scm.properties(path, identifier) end - def cat(path, identifier=nil) - scm.cat(path, identifier) + def cat(path, identifier=nil, &block) + scm.cat(path, identifier, &block) end def diff(path, rev, rev_to) diff -r 92fbf3063e7b lib/buffered_io.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/buffered_io.rb Mon Dec 08 12:04:28 2008 +0100 @@ -0,0 +1,137 @@ +# 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 BufferedIO + + attr_accessor :cache + + def initialize(io) + @source = io + @cache = false + @synced = true + end + + def cache=(b) + if b and synced? + @cache = true + else + @cache = false + end + end + + def internal_buffer + @internal_buffer || @internal_buffer = StringIO.new + end + + def is_binary_data? + if synced? + position = internal_buffer.pos + internal_buffer.rewind + s = read_and_cache(4096) + internal_buffer.pos = position + s.is_binary_data? + else + raise Exception.new("Cannot do this test on an uncached buffer") + end + end + + def synced? + @synced + end + + def read(x=nil) + if cache + read_and_cache(x) + else + read_and_dont_cache(x) + end + end + + def pos=(x) + if x > internal_buffer.size + if sinced? and cache + _append @source.read(x - internal_buffer.pos) + internal_buffer.pos = x + else + @source.pos = x + end + else + internal_buffer.pos = x + end + end + + ["pos", "rewind", "tell"].each do |m| + define_method(m) do + if synced? + internal_buffer.send(m) + else + @source.send(m) + end + end + end + + def close + @source.close + end + + private + + def _append(s) + unless s.nil? + internal_buffer << s + internal_buffer.pos -= s.size + end + end + + def read_source(x) + @synced = false + @source.read(x) + end + + # Read the buffer by filling readed data in the cache. + def read_and_cache(x=nil) + if synced? + to_read = x ? to_read = x + internal_buffer.pos - internal_buffer.size : nil + _append(@source.read(to_read)) if to_read.nil? or to_read > 0 + internal_buffer.read(x) + else + # Data is missing + raise "Cannot cache a partially cached stream" + end + end + + # Read without filling the cache and ram by the way. + # Not cached data will not be readable anymore if the + # buffer cannot rewind. + def read_and_dont_cache(x=nil) + if synced? + # Source and cache buffer are synced + if internal_buffer.pos == internal_buffer.size + # There is nothing to read in the cache + read_source(x) + else # internal_buffer.pos < @source.pos + if x.nil? or (internal_buffer.pos + x) > internal_buffer.size + # There is a first part to read in the cache + # and another in the source + internal_buffer.read + read_source(x) + else + # All is in the cache + internal_buffer.read(x) + end + end + else + @internal_buffer = nil + read_source(x) + end + end +end diff -r 92fbf3063e7b lib/redmine/scm/adapters/abstract_adapter.rb --- a/lib/redmine/scm/adapters/abstract_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/abstract_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -113,7 +113,7 @@ return nil end - def cat(path, identifier=nil) + def cat(path, identifier=nil, &block) return nil end @@ -172,9 +172,15 @@ def self.shellout(cmd, &block) logger.debug "Shelling out: #{cmd}" if logger && logger.debug? begin - IO.popen(cmd, "r+") do |io| + if block_given? + IO.popen(cmd, "r+") do |io| + io.close_write + block.call(io) + end + else + io = IO.popen(cmd, "r+") io.close_write - block.call(io) if block_given? + return io end rescue Errno::ENOENT => e msg = strip_credential(e.message) diff -r 92fbf3063e7b lib/redmine/scm/adapters/bazaar_adapter.rb --- a/lib/redmine/scm/adapters/bazaar_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/bazaar_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -151,17 +151,21 @@ diff end - def cat(path, identifier=nil) + def cat(path, identifier=nil, &block) cmd = "#{BZR_BIN} cat" cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0 cmd << " #{target(path)}" cat = nil - shellout(cmd) do |io| + if block_given? + shellout(cmd) do |io| + io.binmode + yield BufferedIO.new(io) + end + else + io = shellout(cmd) io.binmode - cat = io.read + return BufferedIO.new(io) end - return nil if $? && $?.exitstatus != 0 - cat end def annotate(path, identifier=nil) diff -r 92fbf3063e7b lib/redmine/scm/adapters/cvs_adapter.rb --- a/lib/redmine/scm/adapters/cvs_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/cvs_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -240,7 +240,7 @@ diff end - def cat(path, identifier=nil) + def cat(path, identifier=nil, &block) identifier = (identifier) ? identifier : "HEAD" logger.debug " cat path:'#{path}',identifier #{identifier}" path_with_project="#{url}#{with_leading_slash(path)}" @@ -248,11 +248,16 @@ cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier cmd << " -p #{shell_quote path_with_project}" cat = nil - shellout(cmd) do |io| - cat = io.read + if block_given? + shellout(cmd) do |io| + io.binmode + yield BufferedIO.new(io) + end + else + io = shellout(cmd) + io.binmode + return BufferedIO.new(io) end - return nil if $? && $?.exitstatus != 0 - cat end def annotate(path, identifier=nil) diff -r 92fbf3063e7b lib/redmine/scm/adapters/darcs_adapter.rb --- a/lib/redmine/scm/adapters/darcs_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/darcs_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -134,17 +134,21 @@ diff end - def cat(path, identifier=nil) + def cat(path, identifier=nil, &block) cmd = "#{DARCS_BIN} show content --repodir #{@url}" cmd << " --match \"hash #{identifier}\"" if identifier cmd << " #{shell_quote path}" cat = nil - shellout(cmd) do |io| + if block_given? + shellout(cmd) do |io| + io.binmode + yield BufferedIO.new(io) + end + else + io = shellout(cmd) io.binmode - cat = io.read + return BufferedIO.new(io) end - return nil if $? && $?.exitstatus != 0 - cat end private diff -r 92fbf3063e7b lib/redmine/scm/adapters/filesystem_adapter.rb --- a/lib/redmine/scm/adapters/filesystem_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/filesystem_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -71,8 +71,17 @@ entries.sort_by_name end - def cat(path, identifier=nil) - File.new(target(path), "rb").read + def cat(path, identifier=nil, &block) + if block_given? + File.open(target(path), "rb") do |io| + io.binmode + yield BufferedIO.new(io) + end + else + io = File.new(target(path), "rb") + io.binmode + return BufferedIO.new(io) + end end private diff -r 92fbf3063e7b lib/redmine/scm/adapters/git_adapter.rb --- a/lib/redmine/scm/adapters/git_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/git_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -249,18 +249,22 @@ blame end - def cat(path, identifier=nil) + def cat(path, identifier=nil, &block) if identifier.nil? identifier = 'HEAD' end cmd = "#{GIT_BIN} --git-dir #{target('')} show #{shell_quote(identifier + ':' + path)}" cat = nil - shellout(cmd) do |io| + if block_given? + shellout(cmd) do |io| + io.binmode + yield BufferedIO.new(io) + end + else + io = shellout(cmd) io.binmode - cat = io.read + return BufferedIO.new(io) end - return nil if $? && $?.exitstatus != 0 - cat end end end diff -r 92fbf3063e7b lib/redmine/scm/adapters/mercurial_adapter.rb --- a/lib/redmine/scm/adapters/mercurial_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -92,6 +92,7 @@ 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 entries.detect{|entry| entry.name == e.first} end @@ -169,17 +170,21 @@ diff end - def cat(path, identifier=nil) + def cat(path, identifier=nil, &block) cmd = "#{HG_BIN} -R #{target('')} cat" cmd << " -r " + (identifier ? identifier.to_s : "tip") cmd << " #{target(path)}" cat = nil - shellout(cmd) do |io| + if block_given? + shellout(cmd) do |io| + io.binmode + yield BufferedIO.new(io) + end + else + io = shellout(cmd) io.binmode - cat = io.read + return BufferedIO.new(io) end - return nil if $? && $?.exitstatus != 0 - cat end def annotate(path, identifier=nil) diff -r 92fbf3063e7b lib/redmine/scm/adapters/subversion_adapter.rb --- a/lib/redmine/scm/adapters/subversion_adapter.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/lib/redmine/scm/adapters/subversion_adapter.rb Mon Dec 08 12:04:28 2008 +0100 @@ -190,17 +190,23 @@ diff end - def cat(path, identifier=nil) + def cat(path, identifier=nil, &block) identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD" cmd = "#{SVN_BIN} cat #{target(URI.escape(path))}@#{identifier}" cmd << credentials_string cat = nil - shellout(cmd) do |io| + if block_given? + shellout(cmd) do |io| + io.binmode + yield BufferedIO.new(io) + end + else + io = shellout(cmd) io.binmode - cat = io.read + return BufferedIO.new(io) end - return nil if $? && $?.exitstatus != 0 - cat + ensure + io.close if (io and block_given?) end def annotate(path, identifier=nil) diff -r 92fbf3063e7b test/functional/repositories_cvs_controller_test.rb --- a/test/functional/repositories_cvs_controller_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/functional/repositories_cvs_controller_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -22,6 +22,9 @@ class RepositoriesController; def rescue_action(e) raise e end; end class RepositoriesCvsControllerTest < Test::Unit::TestCase + fixtures :projects, :users, :roles, :members, :enabled_modules, + :issues, :issue_statuses, :changesets, :changes, + :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers # No '..' in the repository path REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/cvs_repository' @@ -113,6 +116,13 @@ def test_entry_download get :entry, :id => 1, :path => ['sources', 'watchers_controller.rb'], :format => 'raw' assert_response :success + + content = StringIO.new + r = nil + @response.body.call(r, content) + content.rewind + content = content.read.split("\n") + assert_equal "end", content.last end def test_directory_entry diff -r 92fbf3063e7b test/functional/repositories_mercurial_controller_test.rb --- a/test/functional/repositories_mercurial_controller_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/functional/repositories_mercurial_controller_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -97,7 +97,13 @@ get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb'], :format => 'raw' assert_response :success # File content - assert @response.body.include?('WITHOUT ANY WARRANTY') + content = StringIO.new + r = nil + @response.body.call(r, content) + content.rewind + content = content.read + assert content.include?('WITHOUT ANY WARRANTY') + assert_equal "end", content.split("\r\n").last end def test_directory_entry diff -r 92fbf3063e7b test/functional/repositories_subversion_controller_test.rb --- a/test/functional/repositories_subversion_controller_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/functional/repositories_subversion_controller_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -111,6 +111,13 @@ def test_entry_download get :entry, :id => 1, :path => ['subversion_test', 'helloworld.c'], :format => 'raw' assert_response :success + content = StringIO.new + r = nil + @response.body.call(r, content) + content.rewind + content = content.read.split("\r\n") + assert_equal "#include ", content.first + assert_equal "}", content.last end def test_directory_entry diff -r 92fbf3063e7b test/unit/lib/buffered_io_test.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/lib/buffered_io_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -0,0 +1,50 @@ +# 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. + +require File.dirname(__FILE__) + '/../../test_helper' + +class BufferedIOTest < Test::Unit::TestCase + + CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + def self.rand_string(length=8) + s='' + length.times{ s << CHARS[rand(CHARS.length)] } + s + end + + TEST_STRING=rand_string(1000) + + def test_stop_caching + io = BufferedIO.new(StringIO.new(TEST_STRING)) + io.cache = true + t = io.read(5) + assert_equal 5, io.internal_buffer.size + io.cache = false + t += io.read + assert_equal TEST_STRING, t + assert_equal 5, io.internal_buffer.size + end + + def test_is_binary_data + io = BufferedIO.new(StringIO.new(TEST_STRING)) + io2 = BufferedIO.new(StringIO.new(TEST_STRING)) + io2.cache = true + [io, io2].each do |io| + assert_equal false, io.is_binary_data? + t = io.read + assert_equal TEST_STRING, t + end + end + +end diff -r 92fbf3063e7b test/unit/repository_bazaar_test.rb --- a/test/unit/repository_bazaar_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/unit/repository_bazaar_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -70,8 +70,10 @@ end def test_cat - cat = @repository.scm.cat('directory/document.txt') - assert cat =~ /Write the contents of a file as of a given revision to standard output/ + @repository.scm.cat('directory/document.txt') do |io| + cat = io.read + assert cat =~ /Write the contents of a file as of a given revision to standard output/ + end end def test_annotate diff -r 92fbf3063e7b test/unit/repository_cvs_test.rb --- a/test/unit/repository_cvs_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/unit/repository_cvs_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -53,6 +53,12 @@ @repository.fetch_changesets assert_equal 5, @repository.changesets.count end + + def test_cat + content = @repository.scm.cat("sources/watchers_controller.rb").read.split("\n") + assert_equal "end", content.last + end + else puts "CVS test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end diff -r 92fbf3063e7b test/unit/repository_darcs_test.rb --- a/test/unit/repository_darcs_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/unit/repository_darcs_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -51,7 +51,7 @@ def test_cat @repository.fetch_changesets - cat = @repository.cat("sources/welcome_controller.rb", 2) + cat = @repository.cat("sources/welcome_controller.rb", 2).read assert_not_nil cat assert cat.include?('class WelcomeController < ApplicationController') end diff -r 92fbf3063e7b test/unit/repository_filesystem_test.rb --- a/test/unit/repository_filesystem_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/unit/repository_filesystem_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -44,7 +44,9 @@ end def test_cat - assert_equal "TEST CAT\n", @repository.scm.cat("test") + @repository.scm.cat("test") do |io| + assert_equal "TEST CAT\n", io.read + end end else diff -r 92fbf3063e7b test/unit/repository_git_test.rb --- a/test/unit/repository_git_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/unit/repository_git_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -62,6 +62,17 @@ @repository.fetch_changesets assert_equal 6, @repository.changesets.count end + + def test_cat + @repository.cat("README") do |io| + cat = io.read + assert_not_nil cat + lines = cat.split("\r\n") + assert_equal 'Mercurial test repository', lines.first + assert_equal 'It is written in Python.', lines.last + end + end + else puts "Git test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end diff -r 92fbf3063e7b test/unit/repository_subversion_test.rb --- a/test/unit/repository_subversion_test.rb Sun Dec 07 16:21:40 2008 +0100 +++ b/test/unit/repository_subversion_test.rb Mon Dec 08 12:04:28 2008 +0100 @@ -48,6 +48,13 @@ @repository.fetch_changesets assert_equal 8, @repository.changesets.count end + + def test_cat + content = @repository.cat("subversion_test/helloworld.c").read.split("\r\n") + assert_equal "#include ", content.first + assert_equal "}", content.last + end + else puts "Subversion test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end