"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
This commit is contained in:
parent
8b5ebd92c9
commit
8b98c05879
|
@ -111,7 +111,7 @@ default:
|
|||
# Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
|
||||
# On Windows, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
|
||||
scm_subversion_command: svn # (default: svn)
|
||||
scm_mercurial_command: "\"C:\Program Files\TortoiseHg\hg.exe\"" # (default: hg)
|
||||
scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
|
||||
scm_git_command: /usr/local/bin/git # (default: git)
|
||||
scm_cvs_command: cvs # (default: cvs)
|
||||
scm_bazaar_command: bzr.exe # (default: bzr)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "<cvs> 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 "<cvs> 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 "<cvs> 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 "<cvs> 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 "<cvs> 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 "<cvs> 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|
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)}"
|
||||
|
|
|
@ -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|
|
||||
|
|
Loading…
Reference in New Issue