From 3edbab734b76ab3938b384ba1c77f8a162818ff1 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Thu, 10 Feb 2011 18:13:10 +0000 Subject: [PATCH 01/13] scm: subversion: prepare version string unit lib test. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4803 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/subversion_adapter_test.rb | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb index 99e8ceb2..966a8292 100644 --- a/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb @@ -17,15 +17,27 @@ require File.expand_path('../../../../../../test_helper', __FILE__) -class SubversionAdapterTest < ActiveSupport::TestCase +begin + require 'mocha' + + class SubversionAdapterTest < ActiveSupport::TestCase - if repository_configured?('subversion') - def test_client_version - v = Redmine::Scm::Adapters::SubversionAdapter.client_version - assert v.is_a?(Array) + if repository_configured?('subversion') + def setup + end + + def test_client_version + v = Redmine::Scm::Adapters::SubversionAdapter.client_version + assert v.is_a?(Array) + end + else + puts "Subversion test repository NOT FOUND. Skipping unit tests !!!" + def test_fake; assert true end end - else - puts "Subversion test repository NOT FOUND. Skipping unit tests !!!" - def test_fake; assert true end + end + +rescue LoadError + class SubversionMochaFake < ActiveSupport::TestCase + def test_fake; assert(false, "Requires mocha to run those tests") end end end From 09e0aa32b8b80351dadd66f05e50b9f4c8d18fed Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 11 Feb 2011 15:29:56 +0000 Subject: [PATCH 02/13] scm: cvs: code clean up. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4804 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/cvs_adapter.rb | 48 ++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb index 5c81e639..803af604 100644 --- a/lib/redmine/scm/adapters/cvs_adapter.rb +++ b/lib/redmine/scm/adapters/cvs_adapter.rb @@ -55,7 +55,7 @@ module Redmine def get_previous_revision(revision) CvsRevisionHelper.new(revision).prevRev end - + # Returns an Entries collection # or nil if the given path doesn't exist in the repository # this method is used by the repository-browser (aka LIST) @@ -70,7 +70,7 @@ module Redmine io.each_line(){|line| fields=line.chop.split('/',-1) logger.debug(">>InspectLine #{fields.inspect}") - + if fields[0]!="D" entries << Entry.new({:name => fields[-5], #:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]), @@ -96,17 +96,17 @@ module Redmine end return nil if $? && $?.exitstatus != 0 entries.sort_by_name - end + end STARTLOG="----------------------------" ENDLOG ="=============================================================================" - + # Returns all revisions found between identifier_from and identifier_to # in the repository. both identifier have to be dates or nil. # these method returns nothing but yield every result in block def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block) logger.debug " revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" - + path_with_project="#{url}#{with_leading_slash(path)}" cmd = "#{CVS_BIN} -d #{shell_quote root_url} rlog" cmd << " -d\">#{time_to_cvstime_rlog(identifier_from)}\"" if identifier_from @@ -123,7 +123,7 @@ module Redmine file_state=nil branch_map=nil - io.each_line() do |line| + io.each_line() do |line| if state!="revision" && /^#{ENDLOG}/ =~ line commit_log=String.new @@ -162,9 +162,9 @@ module Redmine end next elsif state=="revision" - if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line + if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line if revision - + revHelper=CvsRevisionHelper.new(revision) revBranch="HEAD" @@ -176,7 +176,7 @@ module Redmine logger.debug("********** YIELD Revision #{revision}::#{revBranch}") - yield Revision.new({ + yield Revision.new({ :time => date, :author => author, :message=>commit_log.chomp, @@ -188,9 +188,9 @@ module Redmine :kind=>'file', :action=>file_state }] - }) + }) end - + commit_log=String.new revision=nil @@ -199,7 +199,7 @@ module Redmine end next end - + if /^branches: (.+)$/ =~ line #TODO: version.branch = $1 elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line @@ -216,16 +216,16 @@ module Redmine # version.line_minus = linechanges[2] # else # version.line_plus = 0 - # version.line_minus = 0 - # end - else + # version.line_minus = 0 + # end + else commit_log << line unless line =~ /^\*\*\* empty log message \*\*\*/ - end - end + end + end end end - end - + end + def diff(path, identifier_from, identifier_to=nil) logger.debug " diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" path_with_project="#{url}#{with_leading_slash(path)}" @@ -238,8 +238,8 @@ module Redmine end return nil if $? && $?.exitstatus != 0 diff - end - + end + def cat(path, identifier=nil) identifier = (identifier) ? identifier : "HEAD" logger.debug " cat path:'#{path}',identifier #{identifier}" @@ -253,7 +253,7 @@ module Redmine end return nil if $? && $?.exitstatus != 0 cat - end + end def annotate(path, identifier=nil) identifier = (identifier) ? identifier.to_i : "HEAD" @@ -270,9 +270,9 @@ module Redmine return nil if $? && $?.exitstatus != 0 blame end - + private - + # Returns the root url without the connexion string # :pserver:anonymous@foo.bar:/path => /path # :ext:cvsservername:/path => /path From dd798edd0458e6b9bf6c2dac68b2a0faf42d5ad9 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 11 Feb 2011 15:30:22 +0000 Subject: [PATCH 03/13] scm: git: prepare version string unit lib test and git log encoding (#3396). This file includes UTF-8 literal. We need to consider Ruby 1.9 compatibity. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4805 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../redmine/scm/adapters/git_adapter_test.rb | 143 ++++++++++-------- 1 file changed, 82 insertions(+), 61 deletions(-) diff --git a/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb index bc9959dc..972363f2 100644 --- a/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb @@ -1,71 +1,92 @@ # encoding: utf-8 +# This file includes UTF-8 "Felix Schäfer". +# We need to consider Ruby 1.9 compatibity. + require File.expand_path('../../../../../../test_helper', __FILE__) +begin + require 'mocha' -class GitAdapterTest < ActiveSupport::TestCase - REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository' + class GitAdapterTest < ActiveSupport::TestCase + REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository' - if File.directory?(REPOSITORY_PATH) - def setup - @adapter = Redmine::Scm::Adapters::GitAdapter.new(REPOSITORY_PATH) - end + if File.directory?(REPOSITORY_PATH) + def setup + @adapter = Redmine::Scm::Adapters::GitAdapter.new(REPOSITORY_PATH) + end - def test_branches - assert_equal @adapter.branches, ['master', 'test_branch'] - end + def test_branches + assert_equal @adapter.branches, ['master', 'test_branch'] + end - def test_getting_all_revisions - assert_equal 15, @adapter.revisions('',nil,nil,:all => true).length + def test_getting_all_revisions + assert_equal 15, @adapter.revisions('',nil,nil,:all => true).length + end + + def test_getting_certain_revisions + assert_equal 1, @adapter.revisions('','899a15d^','899a15d').length + end + + def test_getting_revisions_with_spaces_in_filename + assert_equal 1, @adapter.revisions("filemane with spaces.txt", + nil, nil, :all => true).length + end + + def test_getting_revisions_with_leading_and_trailing_spaces_in_filename + assert_equal " filename with a leading space.txt ", + @adapter.revisions(" filename with a leading space.txt ", + nil, nil, :all => true)[0].paths[0][:path] + end + + def test_getting_entries_with_leading_and_trailing_spaces_in_filename + assert_equal " filename with a leading space.txt ", + @adapter.entries('', + '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name + end + + def test_annotate + annotate = @adapter.annotate('sources/watchers_controller.rb') + assert_kind_of Redmine::Scm::Adapters::Annotate, annotate + assert_equal 41, annotate.lines.size + assert_equal "# This program is free software; you can redistribute it and/or", annotate.lines[4].strip + assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", + annotate.revisions[4].identifier + assert_equal "jsmith", annotate.revisions[4].author + end + + def test_annotate_moved_file + annotate = @adapter.annotate('renamed_test.txt') + assert_kind_of Redmine::Scm::Adapters::Annotate, annotate + assert_equal 2, annotate.lines.size + end + + def test_last_rev + last_rev = @adapter.lastrev("README", + "4f26664364207fa8b1af9f8722647ab2d4ac5d43") + assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid + assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier + assert_equal "Adam Soltys ", last_rev.author + assert_equal "2009-06-24 05:27:38".to_time, last_rev.time + end + + def test_last_rev_with_spaces_in_filename + last_rev = @adapter.lastrev("filemane with spaces.txt", + "ed5bb786bbda2dee66a2d50faf51429dbc043a7b") + assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid + assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier + assert_equal "Felix Schäfer ", + last_rev.author + assert_equal "2010-09-18 19:59:46".to_time, last_rev.time + end + else + puts "Git test repository NOT FOUND. Skipping unit tests !!!" + def test_fake; assert true end end - - def test_getting_certain_revisions - assert_equal 1, @adapter.revisions('','899a15d^','899a15d').length - end - - def test_getting_revisions_with_spaces_in_filename - assert_equal 1, @adapter.revisions("filemane with spaces.txt", nil, nil, :all => true).length - end - - def test_getting_revisions_with_leading_and_trailing_spaces_in_filename - assert_equal " filename with a leading space.txt ", @adapter.revisions(" filename with a leading space.txt ", nil, nil, :all => true)[0].paths[0][:path] - end - - def test_getting_entries_with_leading_and_trailing_spaces_in_filename - assert_equal " filename with a leading space.txt ", @adapter.entries('', '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name - end - - def test_annotate - annotate = @adapter.annotate('sources/watchers_controller.rb') - assert_kind_of Redmine::Scm::Adapters::Annotate, annotate - assert_equal 41, annotate.lines.size - assert_equal "# This program is free software; you can redistribute it and/or", annotate.lines[4].strip - assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", annotate.revisions[4].identifier - assert_equal "jsmith", annotate.revisions[4].author - end - - def test_annotate_moved_file - annotate = @adapter.annotate('renamed_test.txt') - assert_kind_of Redmine::Scm::Adapters::Annotate, annotate - assert_equal 2, annotate.lines.size - end - - def test_last_rev - last_rev = @adapter.lastrev("README", "4f26664364207fa8b1af9f8722647ab2d4ac5d43") - assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid - assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier - assert_equal "Adam Soltys ", last_rev.author - assert_equal "2009-06-24 05:27:38".to_time, last_rev.time - end - - def test_last_rev_with_spaces_in_filename - last_rev = @adapter.lastrev("filemane with spaces.txt", "ed5bb786bbda2dee66a2d50faf51429dbc043a7b") - assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid - assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier - assert_equal "Felix Schäfer ", last_rev.author - assert_equal "2010-09-18 19:59:46".to_time, last_rev.time - end - else - puts "Git test repository NOT FOUND. Skipping unit tests !!!" - def test_fake; assert true end + end + +rescue LoadError + class GitMochaFake < ActiveSupport::TestCase + def test_fake; assert(false, "Requires mocha to run those tests") end end end + From 911fbefb453ea4bfa41c60f14fc8d0b64cb0f7e2 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 11 Feb 2011 15:30:45 +0000 Subject: [PATCH 04/13] scm: change gunzip to tar -z option for scm repository setup in lib/tasks/testing.rake. Pipe does not work on Mingw Ruby. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4806 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/tasks/testing.rake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tasks/testing.rake b/lib/tasks/testing.rake index 1f43a115..266dcf9c 100644 --- a/lib/tasks/testing.rake +++ b/lib/tasks/testing.rake @@ -51,7 +51,8 @@ namespace :test do (supported_scms - [:subversion, :mercurial]).each do |scm| desc "Creates a test #{scm} repository" task scm => :create_dir do - system "gunzip < test/fixtures/repositories/#{scm}_repository.tar.gz | tar -xv -C tmp/test" + # system "gunzip < test/fixtures/repositories/#{scm}_repository.tar.gz | tar -xv -C tmp/test" + system "tar -xvz -C tmp/test -f test/fixtures/repositories/#{scm}_repository.tar.gz" end end From 6b6a44c83197749908604af45d2dc32317daa2a4 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 11 Feb 2011 15:31:11 +0000 Subject: [PATCH 05/13] scm: bazaar: prepare version string unit lib test. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4807 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .../scm/adapters/bazaar_adapter_test.rb | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb diff --git a/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb new file mode 100644 index 00000000..2fc8f492 --- /dev/null +++ b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb @@ -0,0 +1,26 @@ +require File.expand_path('../../../../../../test_helper', __FILE__) +begin + require 'mocha' + + class BazaarAdapterTest < ActiveSupport::TestCase + + REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/bazaar_repository' + MODULE_NAME = 'test' + + if File.directory?(REPOSITORY_PATH) + def setup + @adapter = Redmine::Scm::Adapters::BazzarAdapter.new(MODULE_NAME, REPOSITORY_PATH) + end + + else + puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!" + def test_fake; assert true end + end + end + +rescue LoadError + class BazaarMochaFake < ActiveSupport::TestCase + def test_fake; assert(false, "Requires mocha to run those tests") end + end +end + From 64835367ab73e77c9ec5d055593adbe61ccf63e3 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 11 Feb 2011 15:32:45 +0000 Subject: [PATCH 06/13] scm: cvs: fix unit lib test fails on Windows. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4808 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb index e063d44f..b6b4b6ee 100644 --- a/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb @@ -5,6 +5,7 @@ begin class CvsAdapterTest < ActiveSupport::TestCase REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/cvs_repository' + REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin? MODULE_NAME = 'test' if File.directory?(REPOSITORY_PATH) From 3110e97038b3b2c4aeccdd6adc87b6d5dc66fcc5 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 11 Feb 2011 15:44:52 +0000 Subject: [PATCH 07/13] scm: git: fix typo of unit lib test. This file includes UTF-8 "literal". We need to consider Ruby 1.9 compatibility. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4809 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/lib/redmine/scm/adapters/git_adapter_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb index 972363f2..049296d9 100644 --- a/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 # This file includes UTF-8 "Felix Schäfer". -# We need to consider Ruby 1.9 compatibity. +# We need to consider Ruby 1.9 compatibility. require File.expand_path('../../../../../../test_helper', __FILE__) begin From 2b979920150a40d8e4490e33d2395b9ca36b9b26 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Fri, 11 Feb 2011 16:00:57 +0000 Subject: [PATCH 08/13] scm: bazaar: fix typo and mistakes. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4810 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb index 2fc8f492..82372bbb 100644 --- a/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb +++ b/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb @@ -5,11 +5,10 @@ begin class BazaarAdapterTest < ActiveSupport::TestCase REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/bazaar_repository' - MODULE_NAME = 'test' if File.directory?(REPOSITORY_PATH) def setup - @adapter = Redmine::Scm::Adapters::BazzarAdapter.new(MODULE_NAME, REPOSITORY_PATH) + @adapter = Redmine::Scm::Adapters::BazaarAdapter.new(MODULE_NAME, REPOSITORY_PATH) end else From 5356140f5f53840e7689639c2c92e65072819eab Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Barth Date: Sat, 12 Feb 2011 09:02:02 +0000 Subject: [PATCH 09/13] Ignore .project and .loadpath files for hg/git mirrors. #7497 git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4813 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .gitignore | 2 ++ .hgignore | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index ff5865c8..123812cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +/.project +/.loadpath /config/additional_environment.rb /config/configuration.yml /config/database.yml diff --git a/.hgignore b/.hgignore index 5f41fda1..733faf9f 100644 --- a/.hgignore +++ b/.hgignore @@ -1,5 +1,7 @@ syntax: glob +.project +.loadpath config/additional_environment.rb config/configuration.yml config/database.yml From 52822ad58e463e5719bc7f4db5957c75b1fd7d1f Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 12 Feb 2011 09:43:57 +0000 Subject: [PATCH 10/13] scm: cvs: fix most binary files become corrupted on Windows (#6090). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4815 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/cvs_adapter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb index 803af604..1cda3025 100644 --- a/lib/redmine/scm/adapters/cvs_adapter.rb +++ b/lib/redmine/scm/adapters/cvs_adapter.rb @@ -249,6 +249,7 @@ module Redmine cmd << " -p #{shell_quote path_with_project}" cat = nil shellout(cmd) do |io| + io.binmode cat = io.read end return nil if $? && $?.exitstatus != 0 From 3d11a22624339e818067ba3839a46caccf6a0966 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 12 Feb 2011 09:44:23 +0000 Subject: [PATCH 11/13] scm: fix non ASCII filename downloaded from repo is broken on Internet Explorer (#7288). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4816 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/repositories_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 50a6ff4a..74d420e5 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -124,7 +124,7 @@ class RepositoriesController < ApplicationController (show_error_not_found; return) unless @content if 'raw' == params[:format] || @content.is_binary_data? || (@entry.size && @entry.size > Setting.file_max_size_displayed.to_i.kilobyte) # Force the download - send_data @content, :filename => @path.split('/').last + send_data @content, :filename => filename_for_content_disposition(@path.split('/').last) else # Prevent empty lines when displaying a file with Windows style eol @content.gsub!("\r\n", "\n") From 6cd9bc5ca57213245d5cc85b3f20b14b1e24b91a Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Sat, 12 Feb 2011 09:44:46 +0000 Subject: [PATCH 12/13] scm: space and tab cleanup of app/controllers/repositories_controller.rb. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4817 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/repositories_controller.rb | 35 +++++++++++----------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 74d420e5..de44f1d0 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -67,13 +67,13 @@ class RepositoriesController < ApplicationController redirect_to :action => 'committers', :id => @project end end - + def destroy @repository.destroy redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository' end - - def show + + def show @repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty? @entries = @repository.entries(@path, @rev) @@ -88,7 +88,7 @@ class RepositoriesController < ApplicationController end alias_method :browse, :show - + def changes @entry = @repository.entry(@path, @rev) (show_error_not_found; return) unless @entry @@ -96,23 +96,23 @@ class RepositoriesController < ApplicationController @properties = @repository.properties(@path, @rev) @changeset = @repository.find_changeset_by_name(@rev) end - + 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, :repository]) + :limit => @changeset_pages.items_per_page, + :offset => @changeset_pages.current.offset, + :include => [:user, :repository]) respond_to do |format| format.html { render :layout => false if request.xhr? } format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") } end end - + def entry @entry = @repository.entry(@path, @rev) (show_error_not_found; return) unless @entry @@ -122,7 +122,8 @@ class RepositoriesController < ApplicationController @content = @repository.cat(@path, @rev) (show_error_not_found; return) unless @content - if 'raw' == params[:format] || @content.is_binary_data? || (@entry.size && @entry.size > Setting.file_max_size_displayed.to_i.kilobyte) + if 'raw' == params[:format] || @content.is_binary_data? || + (@entry.size && @entry.size > Setting.file_max_size_displayed.to_i.kilobyte) # Force the download send_data @content, :filename => filename_for_content_disposition(@path.split('/').last) else @@ -135,7 +136,7 @@ class RepositoriesController < ApplicationController def annotate @entry = @repository.entry(@path, @rev) (show_error_not_found; return) unless @entry - + @annotate = @repository.scm.annotate(@path, @rev) (render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty? @changeset = @repository.find_changeset_by_name(@rev) @@ -153,7 +154,7 @@ class RepositoriesController < ApplicationController rescue ChangesetNotFound show_error_not_found end - + def diff if params[:format] == 'diff' @diff = @repository.diff(@path, @rev, @rev_to) @@ -185,11 +186,11 @@ class RepositoriesController < ApplicationController end end - def stats + def stats end - + def graph - data = nil + data = nil case params[:graph] when "commits_per_month" data = graph_commits_per_month(@repository) From 6d0fcf556df746a9cd9bcb50a3e01ce68621f432 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 14 Feb 2011 06:14:34 +0000 Subject: [PATCH 13/13] scm: use shell quote for scm command at adapter level (#7517, #4273). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "C:\Program Files\TortoiseHg\hg.exe" can be used in config/configuration.yml. In Ruby 1.9 IO.popen, if cmd is an Array of String, it will be used as the subprocess‘s argv bypassing a shell. See http://www.ruby-doc.org/core/classes/IO.html git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4821 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/scm/adapters/abstract_adapter.rb | 32 +++++++++---- lib/redmine/scm/adapters/bazaar_adapter.rb | 38 +++++++++------ lib/redmine/scm/adapters/cvs_adapter.rb | 30 ++++++++---- lib/redmine/scm/adapters/darcs_adapter.rb | 38 +++++++++------ .../scm/adapters/filesystem_adapter.rb | 7 ++- lib/redmine/scm/adapters/git_adapter.rb | 34 +++++++++---- lib/redmine/scm/adapters/mercurial_adapter.rb | 30 ++++++++---- .../scm/adapters/subversion_adapter.rb | 48 +++++++++++-------- 8 files changed, 168 insertions(+), 89 deletions(-) diff --git a/lib/redmine/scm/adapters/abstract_adapter.rb b/lib/redmine/scm/adapters/abstract_adapter.rb index f98e9095..3442276b 100644 --- a/lib/redmine/scm/adapters/abstract_adapter.rb +++ b/lib/redmine/scm/adapters/abstract_adapter.rb @@ -25,6 +25,10 @@ module Redmine class AbstractAdapter #:nodoc: class << self + def client_command + "" + end + # Returns the version of the scm client # Eg: [1, 5, 0] or [] if unknown def client_version @@ -45,8 +49,20 @@ module Redmine def client_version_above?(v, options={}) ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown]) end + + def client_available + true + end + + def shell_quote(str) + if Redmine::Platform.mswin? + '"' + str.gsub(/"/, '\\"') + '"' + else + "'" + str.gsub(/'/, "'\"'\"'") + "'" + end + end end - + def initialize(url, root_url=nil, login=nil, password=nil) @url = url @login = login if login && !login.empty? @@ -138,7 +154,7 @@ module Redmine path ||= '' (path[-1,1] == "/") ? path : "#{path}/" end - + def without_leading_slash(path) path ||= '' path.gsub(%r{^/+}, '') @@ -148,13 +164,9 @@ module Redmine path ||= '' (path[-1,1] == "/") ? path[0..-2] : path end - + def shell_quote(str) - if Redmine::Platform.mswin? - '"' + str.gsub(/"/, '\\"') + '"' - else - "'" + str.gsub(/'/, "'\"'\"'") + "'" - end + self.class.shell_quote(str) end private @@ -168,11 +180,11 @@ module Redmine base = path.match(/^\//) ? root_url : url shell_quote("#{base}/#{path}".gsub(/[?<>\*]/, '')) end - + def logger self.class.logger end - + def shellout(cmd, &block) self.class.shellout(cmd, &block) end diff --git a/lib/redmine/scm/adapters/bazaar_adapter.rb b/lib/redmine/scm/adapters/bazaar_adapter.rb index 96ec8693..1a11f639 100644 --- a/lib/redmine/scm/adapters/bazaar_adapter.rb +++ b/lib/redmine/scm/adapters/bazaar_adapter.rb @@ -19,15 +19,25 @@ require 'redmine/scm/adapters/abstract_adapter' module Redmine module Scm - module Adapters + module Adapters class BazaarAdapter < AbstractAdapter - + # Bazaar executable name BZR_BIN = Redmine::Configuration['scm_bazaar_command'] || "bzr" - + + class << self + def client_command + @@bin ||= BZR_BIN + end + + def sq_bin + @@sq_bin ||= shell_quote(BZR_BIN) + end + end + # Get info about the repository def info - cmd = "#{BZR_BIN} revno #{target('')}" + cmd = "#{self.class.sq_bin} revno #{target('')}" info = nil shellout(cmd) do |io| if io.read =~ %r{^(\d+)\r?$} @@ -43,13 +53,13 @@ module Redmine rescue CommandFailed return nil end - + # Returns an Entries collection # or nil if the given path doesn't exist in the repository def entries(path=nil, identifier=nil) path ||= '' entries = Entries.new - cmd = "#{BZR_BIN} ls -v --show-ids" + cmd = "#{self.class.sq_bin} ls -v --show-ids" identifier = -1 unless identifier && identifier.to_i > 0 cmd << " -r#{identifier.to_i}" cmd << " #{target(path)}" @@ -71,13 +81,13 @@ module Redmine logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug? entries.sort_by_name end - + def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) path ||= '' identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : 'last:1' identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1 revisions = Revisions.new - cmd = "#{BZR_BIN} log -v --show-ids -r#{identifier_to}..#{identifier_from} #{target(path)}" + cmd = "#{self.class.sq_bin} log -v --show-ids -r#{identifier_to}..#{identifier_from} #{target(path)}" shellout(cmd) do |io| revision = nil parsing = nil @@ -132,7 +142,7 @@ module Redmine return nil if $? && $?.exitstatus != 0 revisions end - + def diff(path, identifier_from, identifier_to=nil) path ||= '' if identifier_to @@ -143,7 +153,7 @@ module Redmine if identifier_from identifier_from = identifier_from.to_i end - cmd = "#{BZR_BIN} diff -r#{identifier_to}..#{identifier_from} #{target(path)}" + cmd = "#{self.class.sq_bin} diff -r#{identifier_to}..#{identifier_from} #{target(path)}" diff = [] shellout(cmd) do |io| io.each_line do |line| @@ -153,9 +163,9 @@ module Redmine #return nil if $? && $?.exitstatus != 0 diff end - + def cat(path, identifier=nil) - cmd = "#{BZR_BIN} cat" + cmd = "#{self.class.sq_bin} cat" cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0 cmd << " #{target(path)}" cat = nil @@ -166,9 +176,9 @@ module Redmine return nil if $? && $?.exitstatus != 0 cat end - + def annotate(path, identifier=nil) - cmd = "#{BZR_BIN} annotate --all" + cmd = "#{self.class.sq_bin} annotate --all" cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0 cmd << " #{target(path)}" blame = Annotate.new diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb index 1cda3025..c3d3bf72 100644 --- a/lib/redmine/scm/adapters/cvs_adapter.rb +++ b/lib/redmine/scm/adapters/cvs_adapter.rb @@ -24,7 +24,17 @@ module Redmine # CVS executable name CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs" - + + class << self + def client_command + @@bin ||= CVS_BIN + end + + def sq_bin + @@sq_bin ||= shell_quote(CVS_BIN) + end + end + # Guidelines for the input: # url -> the project-path, relative to the cvsroot (eg. module name) # root_url -> the good old, sometimes damned, CVSROOT @@ -38,20 +48,20 @@ module Redmine raise CommandFailed if root_url.blank? @root_url = root_url end - + def root_url @root_url end - + def url @url end - + def info logger.debug " info" Info.new({:root_url => @root_url, :lastrev => nil}) end - + def get_previous_revision(revision) CvsRevisionHelper.new(revision).prevRev end @@ -63,7 +73,7 @@ module Redmine logger.debug " entries '#{path}' with identifier '#{identifier}'" path_with_project="#{url}#{with_leading_slash(path)}" entries = Entries.new - cmd = "#{CVS_BIN} -d #{shell_quote root_url} rls -e" + cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rls -e" cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier cmd << " #{shell_quote path_with_project}" shellout(cmd) do |io| @@ -108,7 +118,7 @@ module Redmine logger.debug " revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" path_with_project="#{url}#{with_leading_slash(path)}" - cmd = "#{CVS_BIN} -d #{shell_quote root_url} rlog" + cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rlog" cmd << " -d\">#{time_to_cvstime_rlog(identifier_from)}\"" if identifier_from cmd << " #{shell_quote path_with_project}" shellout(cmd) do |io| @@ -229,7 +239,7 @@ module Redmine def diff(path, identifier_from, identifier_to=nil) logger.debug " diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" path_with_project="#{url}#{with_leading_slash(path)}" - cmd = "#{CVS_BIN} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}" + cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}" diff = [] shellout(cmd) do |io| io.each_line do |line| @@ -244,7 +254,7 @@ module Redmine identifier = (identifier) ? identifier : "HEAD" logger.debug " cat path:'#{path}',identifier #{identifier}" path_with_project="#{url}#{with_leading_slash(path)}" - cmd = "#{CVS_BIN} -d #{shell_quote root_url} co" + cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} co" cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier cmd << " -p #{shell_quote path_with_project}" cat = nil @@ -260,7 +270,7 @@ module Redmine identifier = (identifier) ? identifier.to_i : "HEAD" logger.debug " annotate path:'#{path}',identifier #{identifier}" path_with_project="#{url}#{with_leading_slash(path)}" - cmd = "#{CVS_BIN} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}" + cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}" blame = Annotate.new shellout(cmd) do |io| io.each_line do |line| diff --git a/lib/redmine/scm/adapters/darcs_adapter.rb b/lib/redmine/scm/adapters/darcs_adapter.rb index 4eaf4fff..4eed61e9 100644 --- a/lib/redmine/scm/adapters/darcs_adapter.rb +++ b/lib/redmine/scm/adapters/darcs_adapter.rb @@ -20,16 +20,24 @@ require 'rexml/document' module Redmine module Scm - module Adapters + module Adapters class DarcsAdapter < AbstractAdapter # Darcs executable name DARCS_BIN = Redmine::Configuration['scm_darcs_command'] || "darcs" - + class << self + def client_command + @@bin ||= DARCS_BIN + end + + def sq_bin + @@sq_bin ||= shell_quote(DARCS_BIN) + end + def client_version @@client_version ||= (darcs_binary_version || []) end - + def darcs_binary_version darcsversion = darcs_binary_version_from_command_line if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)}) @@ -38,7 +46,7 @@ module Redmine end def darcs_binary_version_from_command_line - shellout("#{DARCS_BIN} --version") { |io| io.read }.to_s + shellout("#{sq_bin} --version") { |io| io.read }.to_s end end @@ -57,7 +65,7 @@ module Redmine rev = revisions(nil,nil,nil,{:limit => 1}) rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil end - + # Returns an Entries collection # or nil if the given path doesn't exist in the repository def entries(path=nil, identifier=nil) @@ -66,7 +74,7 @@ module Redmine path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' ) end entries = Entries.new - cmd = "#{DARCS_BIN} annotate --repodir #{shell_quote @url} --xml-output" + cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --xml-output" cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier cmd << " #{shell_quote path}" shellout(cmd) do |io| @@ -86,11 +94,11 @@ module Redmine return nil if $? && $?.exitstatus != 0 entries.compact.sort_by_name end - + def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) path = '.' if path.blank? revisions = Revisions.new - cmd = "#{DARCS_BIN} changes --repodir #{shell_quote @url} --xml-output" + cmd = "#{self.class.sq_bin} changes --repodir #{shell_quote @url} --xml-output" cmd << " --from-match #{shell_quote("hash #{identifier_from}")}" if identifier_from cmd << " --last #{options[:limit].to_i}" if options[:limit] shellout(cmd) do |io| @@ -113,10 +121,10 @@ module Redmine return nil if $? && $?.exitstatus != 0 revisions end - + def diff(path, identifier_from, identifier_to=nil) path = '*' if path.blank? - cmd = "#{DARCS_BIN} diff --repodir #{shell_quote @url}" + cmd = "#{self.class.sq_bin} diff --repodir #{shell_quote @url}" if identifier_to.nil? cmd << " --match #{shell_quote("hash #{identifier_from}")}" else @@ -133,9 +141,9 @@ module Redmine return nil if $? && $?.exitstatus != 0 diff end - + def cat(path, identifier=nil) - cmd = "#{DARCS_BIN} show content --repodir #{shell_quote @url}" + cmd = "#{self.class.sq_bin} show content --repodir #{shell_quote @url}" cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier cmd << " #{shell_quote path}" cat = nil @@ -148,7 +156,7 @@ module Redmine end private - + # Returns an Entry from the given XML element # or nil if the entry was deleted def entry_from_xml(element, path_prefix) @@ -196,10 +204,10 @@ module Redmine end paths end - + # Retrieve changed paths for a single patch def get_paths_for_patch_raw(hash) - cmd = "#{DARCS_BIN} annotate --repodir #{shell_quote @url} --summary --xml-output" + cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --summary --xml-output" cmd << " --match #{shell_quote("hash #{hash}")} " paths = [] shellout(cmd) do |io| diff --git a/lib/redmine/scm/adapters/filesystem_adapter.rb b/lib/redmine/scm/adapters/filesystem_adapter.rb index 99296a09..b88892b5 100644 --- a/lib/redmine/scm/adapters/filesystem_adapter.rb +++ b/lib/redmine/scm/adapters/filesystem_adapter.rb @@ -25,7 +25,12 @@ module Redmine module Scm module Adapters class FilesystemAdapter < AbstractAdapter - + + class << self + def client_available + true + end + end def initialize(url, root_url=nil, login=nil, password=nil) @url = with_trailling_slash(url) diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb index a40f4507..a241f839 100644 --- a/lib/redmine/scm/adapters/git_adapter.rb +++ b/lib/redmine/scm/adapters/git_adapter.rb @@ -19,11 +19,25 @@ require 'redmine/scm/adapters/abstract_adapter' module Redmine module Scm - module Adapters + module Adapters class GitAdapter < AbstractAdapter # Git executable name GIT_BIN = Redmine::Configuration['scm_git_command'] || "git" + class << self + def client_command + @@bin ||= GIT_BIN + end + + def sq_bin + @@sq_bin ||= shell_quote(GIT_BIN) + end + + def client_available + !client_version.empty? + end + end + def info begin Info.new(:root_url => url, :lastrev => lastrev('',nil)) @@ -35,7 +49,7 @@ module Redmine def branches return @branches if @branches @branches = [] - cmd = "#{GIT_BIN} --git-dir #{target('')} branch --no-color" + cmd = "#{self.class.sq_bin} --git-dir #{target('')} branch --no-color" shellout(cmd) do |io| io.each_line do |line| @branches << line.match('\s*\*?\s*(.*)$')[1] @@ -46,7 +60,7 @@ module Redmine def tags return @tags if @tags - cmd = "#{GIT_BIN} --git-dir #{target('')} tag" + cmd = "#{self.class.sq_bin} --git-dir #{target('')} tag" shellout(cmd) do |io| @tags = io.readlines.sort!.map{|t| t.strip} end @@ -59,7 +73,7 @@ module Redmine def entries(path=nil, identifier=nil) path ||= '' entries = Entries.new - cmd = "#{GIT_BIN} --git-dir #{target('')} ls-tree -l " + cmd = "#{self.class.sq_bin} --git-dir #{target('')} ls-tree -l " cmd << shell_quote("HEAD:" + path) if identifier.nil? cmd << shell_quote(identifier + ":" + path) if identifier shellout(cmd) do |io| @@ -86,7 +100,7 @@ module Redmine def lastrev(path,rev) return nil if path.nil? - cmd = "#{GIT_BIN} --git-dir #{target('')} log --no-color --date=iso --pretty=fuller --no-merges -n 1 " + cmd = "#{self.class.sq_bin} --git-dir #{target('')} log --no-color --date=iso --pretty=fuller --no-merges -n 1 " cmd << " #{shell_quote rev} " if rev cmd << "-- #{shell_quote path} " unless path.empty? lines = [] @@ -114,7 +128,7 @@ module Redmine def revisions(path, identifier_from, identifier_to, options={}) revisions = Revisions.new - cmd = "#{GIT_BIN} --git-dir #{target('')} log --no-color --raw --date=iso --pretty=fuller " + cmd = "#{self.class.sq_bin} --git-dir #{target('')} log --no-color --raw --date=iso --pretty=fuller " cmd << " --reverse " if options[:reverse] cmd << " --all " if options[:all] cmd << " -n #{options[:limit].to_i} " if options[:limit] @@ -209,9 +223,9 @@ module Redmine path ||= '' if identifier_to - cmd = "#{GIT_BIN} --git-dir #{target('')} diff --no-color #{shell_quote identifier_to} #{shell_quote identifier_from}" + cmd = "#{self.class.sq_bin} --git-dir #{target('')} diff --no-color #{shell_quote identifier_to} #{shell_quote identifier_from}" else - cmd = "#{GIT_BIN} --git-dir #{target('')} show --no-color #{shell_quote identifier_from}" + cmd = "#{self.class.sq_bin} --git-dir #{target('')} show --no-color #{shell_quote identifier_from}" end cmd << " -- #{shell_quote path}" unless path.empty? @@ -227,7 +241,7 @@ module Redmine def annotate(path, identifier=nil) identifier = 'HEAD' if identifier.blank? - cmd = "#{GIT_BIN} --git-dir #{target('')} blame -p #{shell_quote identifier} -- #{shell_quote path}" + cmd = "#{self.class.sq_bin} --git-dir #{target('')} blame -p #{shell_quote identifier} -- #{shell_quote path}" blame = Annotate.new content = nil shellout(cmd) { |io| io.binmode; content = io.read } @@ -255,7 +269,7 @@ module Redmine if identifier.nil? identifier = 'HEAD' end - cmd = "#{GIT_BIN} --git-dir #{target('')} show --no-color #{shell_quote(identifier + ':' + path)}" + cmd = "#{self.class.sq_bin} --git-dir #{target('')} show --no-color #{shell_quote(identifier + ':' + path)}" cat = nil shellout(cmd) do |io| io.binmode diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb index f64e70b2..f8f925d4 100644 --- a/lib/redmine/scm/adapters/mercurial_adapter.rb +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb @@ -20,7 +20,7 @@ require 'cgi' module Redmine module Scm - module Adapters + module Adapters class MercurialAdapter < AbstractAdapter # Mercurial executable name @@ -30,11 +30,23 @@ module Redmine TEMPLATE_EXTENSION = "tmpl" class << self + def client_command + @@bin ||= HG_BIN + end + + def sq_bin + @@sq_bin ||= shell_quote(HG_BIN) + end + def client_version @@client_version ||= (hgversion || []) end - def hgversion + def client_available + !client_version.empty? + end + + def hgversion # The hg version is expressed either as a # release number (eg 0.9.5 or 1.0) or as a revision # id composed of 12 hexa characters. @@ -45,7 +57,7 @@ module Redmine end def hgversion_from_command_line - shellout("#{HG_BIN} --version") { |io| io.read }.to_s + shellout("#{sq_bin} --version") { |io| io.read }.to_s end def template_path @@ -63,7 +75,7 @@ module Redmine end def info - cmd = "#{HG_BIN} -R #{target('')} root" + cmd = "#{self.class.sq_bin} -R #{target('')} root" root_url = nil shellout(cmd) do |io| root_url = io.read @@ -80,7 +92,7 @@ module Redmine def entries(path=nil, identifier=nil) path ||= '' entries = Entries.new - cmd = "#{HG_BIN} -R #{target('')} --cwd #{target('')} locate" + cmd = "#{self.class.sq_bin} -R #{target('')} --cwd #{target('')} locate" cmd << " -r #{hgrev(identifier)}" cmd << " " + shell_quote("path:#{path}") unless path.empty? shellout(cmd) do |io| @@ -106,7 +118,7 @@ module Redmine # makes Mercurial produce a xml output. def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) revisions = Revisions.new - cmd = "#{HG_BIN} --debug --encoding utf8 -R #{target('')} log -C --style #{shell_quote self.class.template_path}" + cmd = "#{self.class.sq_bin} --debug --encoding utf8 -R #{target('')} log -C --style #{shell_quote self.class.template_path}" if identifier_from && identifier_to cmd << " -r #{hgrev(identifier_from)}:#{hgrev(identifier_to)}" elsif identifier_from @@ -164,7 +176,7 @@ module Redmine return [] end end - cmd = "#{HG_BIN} -R #{target('')} --config diff.git=false diff --nodates #{diff_args}" + cmd = "#{self.class.sq_bin} -R #{target('')} --config diff.git=false diff --nodates #{diff_args}" cmd << " -I #{target(path)}" unless path.empty? shellout(cmd) do |io| io.each_line do |line| @@ -176,7 +188,7 @@ module Redmine end def cat(path, identifier=nil) - cmd = "#{HG_BIN} -R #{target('')} cat" + cmd = "#{self.class.sq_bin} -R #{target('')} cat" cmd << " -r #{hgrev(identifier)}" cmd << " #{target(path)}" cat = nil @@ -190,7 +202,7 @@ module Redmine def annotate(path, identifier=nil) path ||= '' - cmd = "#{HG_BIN} -R #{target('')}" + cmd = "#{self.class.sq_bin} -R #{target('')}" cmd << " annotate -ncu" cmd << " -r #{hgrev(identifier)}" cmd << " #{target(path)}" diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb index 28ea55e2..c17d7a5e 100644 --- a/lib/redmine/scm/adapters/subversion_adapter.rb +++ b/lib/redmine/scm/adapters/subversion_adapter.rb @@ -20,19 +20,27 @@ require 'uri' module Redmine module Scm - module Adapters + module Adapters class SubversionAdapter < AbstractAdapter - + # SVN executable name SVN_BIN = Redmine::Configuration['scm_subversion_command'] || "svn" - + class << self + def client_command + @@bin ||= SVN_BIN + end + + def sq_bin + @@sq_bin ||= shell_quote(SVN_BIN) + end + def client_version @@client_version ||= (svn_binary_version || []) end - + def svn_binary_version - cmd = "#{SVN_BIN} --version" + cmd = "#{sq_bin} --version" version = nil shellout(cmd) do |io| # Read svn version in first returned line @@ -44,10 +52,10 @@ module Redmine version end end - + # Get info about the svn repository def info - cmd = "#{SVN_BIN} info --xml #{target}" + cmd = "#{self.class.sq_bin} info --xml #{target}" cmd << credentials_string info = nil shellout(cmd) do |io| @@ -70,14 +78,14 @@ module Redmine rescue CommandFailed return nil end - + # Returns an Entries collection # or nil if the given path doesn't exist in the repository def entries(path=nil, identifier=nil) path ||= '' identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD" entries = Entries.new - cmd = "#{SVN_BIN} list --xml #{target(path)}@#{identifier}" + cmd = "#{self.class.sq_bin} list --xml #{target(path)}@#{identifier}" cmd << credentials_string shellout(cmd) do |io| output = io.read @@ -110,13 +118,13 @@ module Redmine logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug? entries.sort_by_name end - + def properties(path, identifier=nil) # proplist xml output supported in svn 1.5.0 and higher return nil unless self.class.client_version_above?([1, 5, 0]) identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD" - cmd = "#{SVN_BIN} proplist --verbose --xml #{target(path)}@#{identifier}" + cmd = "#{self.class.sq_bin} proplist --verbose --xml #{target(path)}@#{identifier}" cmd << credentials_string properties = {} shellout(cmd) do |io| @@ -132,13 +140,13 @@ module Redmine return nil if $? && $?.exitstatus != 0 properties end - + def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) path ||= '' identifier_from = (identifier_from && identifier_from.to_i > 0) ? identifier_from.to_i : "HEAD" identifier_to = (identifier_to && identifier_to.to_i > 0) ? identifier_to.to_i : 1 revisions = Revisions.new - cmd = "#{SVN_BIN} log --xml -r #{identifier_from}:#{identifier_to}" + cmd = "#{self.class.sq_bin} log --xml -r #{identifier_from}:#{identifier_to}" cmd << credentials_string cmd << " --verbose " if options[:with_paths] cmd << " --limit #{options[:limit].to_i}" if options[:limit] @@ -171,13 +179,13 @@ module Redmine return nil if $? && $?.exitstatus != 0 revisions end - + def diff(path, identifier_from, identifier_to=nil, type="inline") path ||= '' identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : '' identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : (identifier_from.to_i - 1) - - cmd = "#{SVN_BIN} diff -r " + + cmd = "#{self.class.sq_bin} diff -r " cmd << "#{identifier_to}:" cmd << "#{identifier_from}" cmd << " #{target(path)}@#{identifier_from}" @@ -191,10 +199,10 @@ module Redmine return nil if $? && $?.exitstatus != 0 diff end - + def cat(path, identifier=nil) identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD" - cmd = "#{SVN_BIN} cat #{target(path)}@#{identifier}" + cmd = "#{self.class.sq_bin} cat #{target(path)}@#{identifier}" cmd << credentials_string cat = nil shellout(cmd) do |io| @@ -204,10 +212,10 @@ module Redmine return nil if $? && $?.exitstatus != 0 cat end - + def annotate(path, identifier=nil) identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD" - cmd = "#{SVN_BIN} blame #{target(path)}@#{identifier}" + cmd = "#{self.class.sq_bin} blame #{target(path)}@#{identifier}" cmd << credentials_string blame = Annotate.new shellout(cmd) do |io|