##// END OF EJS Templates
scm: use shell quote for scm command at adapter level (#7517, #4273)....
Toshi MARUYAMA -
r4701:8b98c05879a2
parent child
Show More
@@ -111,7 +111,7 default:
111 111 # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
112 112 # On Windows, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
113 113 scm_subversion_command: svn # (default: svn)
114 scm_mercurial_command: "\"C:\Program Files\TortoiseHg\hg.exe\"" # (default: hg)
114 scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
115 115 scm_git_command: /usr/local/bin/git # (default: git)
116 116 scm_cvs_command: cvs # (default: cvs)
117 117 scm_bazaar_command: bzr.exe # (default: bzr)
@@ -25,6 +25,10 module Redmine
25 25
26 26 class AbstractAdapter #:nodoc:
27 27 class << self
28 def client_command
29 ""
30 end
31
28 32 # Returns the version of the scm client
29 33 # Eg: [1, 5, 0] or [] if unknown
30 34 def client_version
@@ -45,8 +49,20 module Redmine
45 49 def client_version_above?(v, options={})
46 50 ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown])
47 51 end
52
53 def client_available
54 true
55 end
56
57 def shell_quote(str)
58 if Redmine::Platform.mswin?
59 '"' + str.gsub(/"/, '\\"') + '"'
60 else
61 "'" + str.gsub(/'/, "'\"'\"'") + "'"
62 end
63 end
48 64 end
49
65
50 66 def initialize(url, root_url=nil, login=nil, password=nil)
51 67 @url = url
52 68 @login = login if login && !login.empty?
@@ -138,7 +154,7 module Redmine
138 154 path ||= ''
139 155 (path[-1,1] == "/") ? path : "#{path}/"
140 156 end
141
157
142 158 def without_leading_slash(path)
143 159 path ||= ''
144 160 path.gsub(%r{^/+}, '')
@@ -148,13 +164,9 module Redmine
148 164 path ||= ''
149 165 (path[-1,1] == "/") ? path[0..-2] : path
150 166 end
151
167
152 168 def shell_quote(str)
153 if Redmine::Platform.mswin?
154 '"' + str.gsub(/"/, '\\"') + '"'
155 else
156 "'" + str.gsub(/'/, "'\"'\"'") + "'"
157 end
169 self.class.shell_quote(str)
158 170 end
159 171
160 172 private
@@ -168,11 +180,11 module Redmine
168 180 base = path.match(/^\//) ? root_url : url
169 181 shell_quote("#{base}/#{path}".gsub(/[?<>\*]/, ''))
170 182 end
171
183
172 184 def logger
173 185 self.class.logger
174 186 end
175
187
176 188 def shellout(cmd, &block)
177 189 self.class.shellout(cmd, &block)
178 190 end
@@ -19,15 +19,25 require 'redmine/scm/adapters/abstract_adapter'
19 19
20 20 module Redmine
21 21 module Scm
22 module Adapters
22 module Adapters
23 23 class BazaarAdapter < AbstractAdapter
24
24
25 25 # Bazaar executable name
26 26 BZR_BIN = Redmine::Configuration['scm_bazaar_command'] || "bzr"
27
27
28 class << self
29 def client_command
30 @@bin ||= BZR_BIN
31 end
32
33 def sq_bin
34 @@sq_bin ||= shell_quote(BZR_BIN)
35 end
36 end
37
28 38 # Get info about the repository
29 39 def info
30 cmd = "#{BZR_BIN} revno #{target('')}"
40 cmd = "#{self.class.sq_bin} revno #{target('')}"
31 41 info = nil
32 42 shellout(cmd) do |io|
33 43 if io.read =~ %r{^(\d+)\r?$}
@@ -43,13 +53,13 module Redmine
43 53 rescue CommandFailed
44 54 return nil
45 55 end
46
56
47 57 # Returns an Entries collection
48 58 # or nil if the given path doesn't exist in the repository
49 59 def entries(path=nil, identifier=nil)
50 60 path ||= ''
51 61 entries = Entries.new
52 cmd = "#{BZR_BIN} ls -v --show-ids"
62 cmd = "#{self.class.sq_bin} ls -v --show-ids"
53 63 identifier = -1 unless identifier && identifier.to_i > 0
54 64 cmd << " -r#{identifier.to_i}"
55 65 cmd << " #{target(path)}"
@@ -71,13 +81,13 module Redmine
71 81 logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug?
72 82 entries.sort_by_name
73 83 end
74
84
75 85 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
76 86 path ||= ''
77 87 identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : 'last:1'
78 88 identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1
79 89 revisions = Revisions.new
80 cmd = "#{BZR_BIN} log -v --show-ids -r#{identifier_to}..#{identifier_from} #{target(path)}"
90 cmd = "#{self.class.sq_bin} log -v --show-ids -r#{identifier_to}..#{identifier_from} #{target(path)}"
81 91 shellout(cmd) do |io|
82 92 revision = nil
83 93 parsing = nil
@@ -132,7 +142,7 module Redmine
132 142 return nil if $? && $?.exitstatus != 0
133 143 revisions
134 144 end
135
145
136 146 def diff(path, identifier_from, identifier_to=nil)
137 147 path ||= ''
138 148 if identifier_to
@@ -143,7 +153,7 module Redmine
143 153 if identifier_from
144 154 identifier_from = identifier_from.to_i
145 155 end
146 cmd = "#{BZR_BIN} diff -r#{identifier_to}..#{identifier_from} #{target(path)}"
156 cmd = "#{self.class.sq_bin} diff -r#{identifier_to}..#{identifier_from} #{target(path)}"
147 157 diff = []
148 158 shellout(cmd) do |io|
149 159 io.each_line do |line|
@@ -153,9 +163,9 module Redmine
153 163 #return nil if $? && $?.exitstatus != 0
154 164 diff
155 165 end
156
166
157 167 def cat(path, identifier=nil)
158 cmd = "#{BZR_BIN} cat"
168 cmd = "#{self.class.sq_bin} cat"
159 169 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
160 170 cmd << " #{target(path)}"
161 171 cat = nil
@@ -166,9 +176,9 module Redmine
166 176 return nil if $? && $?.exitstatus != 0
167 177 cat
168 178 end
169
179
170 180 def annotate(path, identifier=nil)
171 cmd = "#{BZR_BIN} annotate --all"
181 cmd = "#{self.class.sq_bin} annotate --all"
172 182 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
173 183 cmd << " #{target(path)}"
174 184 blame = Annotate.new
@@ -24,7 +24,17 module Redmine
24 24
25 25 # CVS executable name
26 26 CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs"
27
27
28 class << self
29 def client_command
30 @@bin ||= CVS_BIN
31 end
32
33 def sq_bin
34 @@sq_bin ||= shell_quote(CVS_BIN)
35 end
36 end
37
28 38 # Guidelines for the input:
29 39 # url -> the project-path, relative to the cvsroot (eg. module name)
30 40 # root_url -> the good old, sometimes damned, CVSROOT
@@ -38,20 +48,20 module Redmine
38 48 raise CommandFailed if root_url.blank?
39 49 @root_url = root_url
40 50 end
41
51
42 52 def root_url
43 53 @root_url
44 54 end
45
55
46 56 def url
47 57 @url
48 58 end
49
59
50 60 def info
51 61 logger.debug "<cvs> info"
52 62 Info.new({:root_url => @root_url, :lastrev => nil})
53 63 end
54
64
55 65 def get_previous_revision(revision)
56 66 CvsRevisionHelper.new(revision).prevRev
57 67 end
@@ -63,7 +73,7 module Redmine
63 73 logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
64 74 path_with_project="#{url}#{with_leading_slash(path)}"
65 75 entries = Entries.new
66 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rls -e"
76 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rls -e"
67 77 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
68 78 cmd << " #{shell_quote path_with_project}"
69 79 shellout(cmd) do |io|
@@ -108,7 +118,7 module Redmine
108 118 logger.debug "<cvs> revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
109 119
110 120 path_with_project="#{url}#{with_leading_slash(path)}"
111 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rlog"
121 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rlog"
112 122 cmd << " -d\">#{time_to_cvstime_rlog(identifier_from)}\"" if identifier_from
113 123 cmd << " #{shell_quote path_with_project}"
114 124 shellout(cmd) do |io|
@@ -229,7 +239,7 module Redmine
229 239 def diff(path, identifier_from, identifier_to=nil)
230 240 logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
231 241 path_with_project="#{url}#{with_leading_slash(path)}"
232 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}"
242 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}"
233 243 diff = []
234 244 shellout(cmd) do |io|
235 245 io.each_line do |line|
@@ -244,7 +254,7 module Redmine
244 254 identifier = (identifier) ? identifier : "HEAD"
245 255 logger.debug "<cvs> cat path:'#{path}',identifier #{identifier}"
246 256 path_with_project="#{url}#{with_leading_slash(path)}"
247 cmd = "#{CVS_BIN} -d #{shell_quote root_url} co"
257 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} co"
248 258 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
249 259 cmd << " -p #{shell_quote path_with_project}"
250 260 cat = nil
@@ -260,7 +270,7 module Redmine
260 270 identifier = (identifier) ? identifier.to_i : "HEAD"
261 271 logger.debug "<cvs> annotate path:'#{path}',identifier #{identifier}"
262 272 path_with_project="#{url}#{with_leading_slash(path)}"
263 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}"
273 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}"
264 274 blame = Annotate.new
265 275 shellout(cmd) do |io|
266 276 io.each_line do |line|
@@ -20,16 +20,24 require 'rexml/document'
20 20
21 21 module Redmine
22 22 module Scm
23 module Adapters
23 module Adapters
24 24 class DarcsAdapter < AbstractAdapter
25 25 # Darcs executable name
26 26 DARCS_BIN = Redmine::Configuration['scm_darcs_command'] || "darcs"
27
27
28 28 class << self
29 def client_command
30 @@bin ||= DARCS_BIN
31 end
32
33 def sq_bin
34 @@sq_bin ||= shell_quote(DARCS_BIN)
35 end
36
29 37 def client_version
30 38 @@client_version ||= (darcs_binary_version || [])
31 39 end
32
40
33 41 def darcs_binary_version
34 42 darcsversion = darcs_binary_version_from_command_line
35 43 if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)})
@@ -38,7 +46,7 module Redmine
38 46 end
39 47
40 48 def darcs_binary_version_from_command_line
41 shellout("#{DARCS_BIN} --version") { |io| io.read }.to_s
49 shellout("#{sq_bin} --version") { |io| io.read }.to_s
42 50 end
43 51 end
44 52
@@ -57,7 +65,7 module Redmine
57 65 rev = revisions(nil,nil,nil,{:limit => 1})
58 66 rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil
59 67 end
60
68
61 69 # Returns an Entries collection
62 70 # or nil if the given path doesn't exist in the repository
63 71 def entries(path=nil, identifier=nil)
@@ -66,7 +74,7 module Redmine
66 74 path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' )
67 75 end
68 76 entries = Entries.new
69 cmd = "#{DARCS_BIN} annotate --repodir #{shell_quote @url} --xml-output"
77 cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --xml-output"
70 78 cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
71 79 cmd << " #{shell_quote path}"
72 80 shellout(cmd) do |io|
@@ -86,11 +94,11 module Redmine
86 94 return nil if $? && $?.exitstatus != 0
87 95 entries.compact.sort_by_name
88 96 end
89
97
90 98 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
91 99 path = '.' if path.blank?
92 100 revisions = Revisions.new
93 cmd = "#{DARCS_BIN} changes --repodir #{shell_quote @url} --xml-output"
101 cmd = "#{self.class.sq_bin} changes --repodir #{shell_quote @url} --xml-output"
94 102 cmd << " --from-match #{shell_quote("hash #{identifier_from}")}" if identifier_from
95 103 cmd << " --last #{options[:limit].to_i}" if options[:limit]
96 104 shellout(cmd) do |io|
@@ -113,10 +121,10 module Redmine
113 121 return nil if $? && $?.exitstatus != 0
114 122 revisions
115 123 end
116
124
117 125 def diff(path, identifier_from, identifier_to=nil)
118 126 path = '*' if path.blank?
119 cmd = "#{DARCS_BIN} diff --repodir #{shell_quote @url}"
127 cmd = "#{self.class.sq_bin} diff --repodir #{shell_quote @url}"
120 128 if identifier_to.nil?
121 129 cmd << " --match #{shell_quote("hash #{identifier_from}")}"
122 130 else
@@ -133,9 +141,9 module Redmine
133 141 return nil if $? && $?.exitstatus != 0
134 142 diff
135 143 end
136
144
137 145 def cat(path, identifier=nil)
138 cmd = "#{DARCS_BIN} show content --repodir #{shell_quote @url}"
146 cmd = "#{self.class.sq_bin} show content --repodir #{shell_quote @url}"
139 147 cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
140 148 cmd << " #{shell_quote path}"
141 149 cat = nil
@@ -148,7 +156,7 module Redmine
148 156 end
149 157
150 158 private
151
159
152 160 # Returns an Entry from the given XML element
153 161 # or nil if the entry was deleted
154 162 def entry_from_xml(element, path_prefix)
@@ -196,10 +204,10 module Redmine
196 204 end
197 205 paths
198 206 end
199
207
200 208 # Retrieve changed paths for a single patch
201 209 def get_paths_for_patch_raw(hash)
202 cmd = "#{DARCS_BIN} annotate --repodir #{shell_quote @url} --summary --xml-output"
210 cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --summary --xml-output"
203 211 cmd << " --match #{shell_quote("hash #{hash}")} "
204 212 paths = []
205 213 shellout(cmd) do |io|
@@ -25,7 +25,12 module Redmine
25 25 module Scm
26 26 module Adapters
27 27 class FilesystemAdapter < AbstractAdapter
28
28
29 class << self
30 def client_available
31 true
32 end
33 end
29 34
30 35 def initialize(url, root_url=nil, login=nil, password=nil)
31 36 @url = with_trailling_slash(url)
@@ -19,11 +19,25 require 'redmine/scm/adapters/abstract_adapter'
19 19
20 20 module Redmine
21 21 module Scm
22 module Adapters
22 module Adapters
23 23 class GitAdapter < AbstractAdapter
24 24 # Git executable name
25 25 GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
26 26
27 class << self
28 def client_command
29 @@bin ||= GIT_BIN
30 end
31
32 def sq_bin
33 @@sq_bin ||= shell_quote(GIT_BIN)
34 end
35
36 def client_available
37 !client_version.empty?
38 end
39 end
40
27 41 def info
28 42 begin
29 43 Info.new(:root_url => url, :lastrev => lastrev('',nil))
@@ -35,7 +49,7 module Redmine
35 49 def branches
36 50 return @branches if @branches
37 51 @branches = []
38 cmd = "#{GIT_BIN} --git-dir #{target('')} branch --no-color"
52 cmd = "#{self.class.sq_bin} --git-dir #{target('')} branch --no-color"
39 53 shellout(cmd) do |io|
40 54 io.each_line do |line|
41 55 @branches << line.match('\s*\*?\s*(.*)$')[1]
@@ -46,7 +60,7 module Redmine
46 60
47 61 def tags
48 62 return @tags if @tags
49 cmd = "#{GIT_BIN} --git-dir #{target('')} tag"
63 cmd = "#{self.class.sq_bin} --git-dir #{target('')} tag"
50 64 shellout(cmd) do |io|
51 65 @tags = io.readlines.sort!.map{|t| t.strip}
52 66 end
@@ -59,7 +73,7 module Redmine
59 73 def entries(path=nil, identifier=nil)
60 74 path ||= ''
61 75 entries = Entries.new
62 cmd = "#{GIT_BIN} --git-dir #{target('')} ls-tree -l "
76 cmd = "#{self.class.sq_bin} --git-dir #{target('')} ls-tree -l "
63 77 cmd << shell_quote("HEAD:" + path) if identifier.nil?
64 78 cmd << shell_quote(identifier + ":" + path) if identifier
65 79 shellout(cmd) do |io|
@@ -86,7 +100,7 module Redmine
86 100
87 101 def lastrev(path,rev)
88 102 return nil if path.nil?
89 cmd = "#{GIT_BIN} --git-dir #{target('')} log --no-color --date=iso --pretty=fuller --no-merges -n 1 "
103 cmd = "#{self.class.sq_bin} --git-dir #{target('')} log --no-color --date=iso --pretty=fuller --no-merges -n 1 "
90 104 cmd << " #{shell_quote rev} " if rev
91 105 cmd << "-- #{shell_quote path} " unless path.empty?
92 106 lines = []
@@ -114,7 +128,7 module Redmine
114 128 def revisions(path, identifier_from, identifier_to, options={})
115 129 revisions = Revisions.new
116 130
117 cmd = "#{GIT_BIN} --git-dir #{target('')} log --no-color --raw --date=iso --pretty=fuller "
131 cmd = "#{self.class.sq_bin} --git-dir #{target('')} log --no-color --raw --date=iso --pretty=fuller "
118 132 cmd << " --reverse " if options[:reverse]
119 133 cmd << " --all " if options[:all]
120 134 cmd << " -n #{options[:limit].to_i} " if options[:limit]
@@ -209,9 +223,9 module Redmine
209 223 path ||= ''
210 224
211 225 if identifier_to
212 cmd = "#{GIT_BIN} --git-dir #{target('')} diff --no-color #{shell_quote identifier_to} #{shell_quote identifier_from}"
226 cmd = "#{self.class.sq_bin} --git-dir #{target('')} diff --no-color #{shell_quote identifier_to} #{shell_quote identifier_from}"
213 227 else
214 cmd = "#{GIT_BIN} --git-dir #{target('')} show --no-color #{shell_quote identifier_from}"
228 cmd = "#{self.class.sq_bin} --git-dir #{target('')} show --no-color #{shell_quote identifier_from}"
215 229 end
216 230
217 231 cmd << " -- #{shell_quote path}" unless path.empty?
@@ -227,7 +241,7 module Redmine
227 241
228 242 def annotate(path, identifier=nil)
229 243 identifier = 'HEAD' if identifier.blank?
230 cmd = "#{GIT_BIN} --git-dir #{target('')} blame -p #{shell_quote identifier} -- #{shell_quote path}"
244 cmd = "#{self.class.sq_bin} --git-dir #{target('')} blame -p #{shell_quote identifier} -- #{shell_quote path}"
231 245 blame = Annotate.new
232 246 content = nil
233 247 shellout(cmd) { |io| io.binmode; content = io.read }
@@ -255,7 +269,7 module Redmine
255 269 if identifier.nil?
256 270 identifier = 'HEAD'
257 271 end
258 cmd = "#{GIT_BIN} --git-dir #{target('')} show --no-color #{shell_quote(identifier + ':' + path)}"
272 cmd = "#{self.class.sq_bin} --git-dir #{target('')} show --no-color #{shell_quote(identifier + ':' + path)}"
259 273 cat = nil
260 274 shellout(cmd) do |io|
261 275 io.binmode
@@ -20,7 +20,7 require 'cgi'
20 20
21 21 module Redmine
22 22 module Scm
23 module Adapters
23 module Adapters
24 24 class MercurialAdapter < AbstractAdapter
25 25
26 26 # Mercurial executable name
@@ -30,11 +30,23 module Redmine
30 30 TEMPLATE_EXTENSION = "tmpl"
31 31
32 32 class << self
33 def client_command
34 @@bin ||= HG_BIN
35 end
36
37 def sq_bin
38 @@sq_bin ||= shell_quote(HG_BIN)
39 end
40
33 41 def client_version
34 42 @@client_version ||= (hgversion || [])
35 43 end
36 44
37 def hgversion
45 def client_available
46 !client_version.empty?
47 end
48
49 def hgversion
38 50 # The hg version is expressed either as a
39 51 # release number (eg 0.9.5 or 1.0) or as a revision
40 52 # id composed of 12 hexa characters.
@@ -45,7 +57,7 module Redmine
45 57 end
46 58
47 59 def hgversion_from_command_line
48 shellout("#{HG_BIN} --version") { |io| io.read }.to_s
60 shellout("#{sq_bin} --version") { |io| io.read }.to_s
49 61 end
50 62
51 63 def template_path
@@ -63,7 +75,7 module Redmine
63 75 end
64 76
65 77 def info
66 cmd = "#{HG_BIN} -R #{target('')} root"
78 cmd = "#{self.class.sq_bin} -R #{target('')} root"
67 79 root_url = nil
68 80 shellout(cmd) do |io|
69 81 root_url = io.read
@@ -80,7 +92,7 module Redmine
80 92 def entries(path=nil, identifier=nil)
81 93 path ||= ''
82 94 entries = Entries.new
83 cmd = "#{HG_BIN} -R #{target('')} --cwd #{target('')} locate"
95 cmd = "#{self.class.sq_bin} -R #{target('')} --cwd #{target('')} locate"
84 96 cmd << " -r #{hgrev(identifier)}"
85 97 cmd << " " + shell_quote("path:#{path}") unless path.empty?
86 98 shellout(cmd) do |io|
@@ -106,7 +118,7 module Redmine
106 118 # makes Mercurial produce a xml output.
107 119 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
108 120 revisions = Revisions.new
109 cmd = "#{HG_BIN} --debug --encoding utf8 -R #{target('')} log -C --style #{shell_quote self.class.template_path}"
121 cmd = "#{self.class.sq_bin} --debug --encoding utf8 -R #{target('')} log -C --style #{shell_quote self.class.template_path}"
110 122 if identifier_from && identifier_to
111 123 cmd << " -r #{hgrev(identifier_from)}:#{hgrev(identifier_to)}"
112 124 elsif identifier_from
@@ -164,7 +176,7 module Redmine
164 176 return []
165 177 end
166 178 end
167 cmd = "#{HG_BIN} -R #{target('')} --config diff.git=false diff --nodates #{diff_args}"
179 cmd = "#{self.class.sq_bin} -R #{target('')} --config diff.git=false diff --nodates #{diff_args}"
168 180 cmd << " -I #{target(path)}" unless path.empty?
169 181 shellout(cmd) do |io|
170 182 io.each_line do |line|
@@ -176,7 +188,7 module Redmine
176 188 end
177 189
178 190 def cat(path, identifier=nil)
179 cmd = "#{HG_BIN} -R #{target('')} cat"
191 cmd = "#{self.class.sq_bin} -R #{target('')} cat"
180 192 cmd << " -r #{hgrev(identifier)}"
181 193 cmd << " #{target(path)}"
182 194 cat = nil
@@ -190,7 +202,7 module Redmine
190 202
191 203 def annotate(path, identifier=nil)
192 204 path ||= ''
193 cmd = "#{HG_BIN} -R #{target('')}"
205 cmd = "#{self.class.sq_bin} -R #{target('')}"
194 206 cmd << " annotate -ncu"
195 207 cmd << " -r #{hgrev(identifier)}"
196 208 cmd << " #{target(path)}"
@@ -20,19 +20,27 require 'uri'
20 20
21 21 module Redmine
22 22 module Scm
23 module Adapters
23 module Adapters
24 24 class SubversionAdapter < AbstractAdapter
25
25
26 26 # SVN executable name
27 27 SVN_BIN = Redmine::Configuration['scm_subversion_command'] || "svn"
28
28
29 29 class << self
30 def client_command
31 @@bin ||= SVN_BIN
32 end
33
34 def sq_bin
35 @@sq_bin ||= shell_quote(SVN_BIN)
36 end
37
30 38 def client_version
31 39 @@client_version ||= (svn_binary_version || [])
32 40 end
33
41
34 42 def svn_binary_version
35 cmd = "#{SVN_BIN} --version"
43 cmd = "#{sq_bin} --version"
36 44 version = nil
37 45 shellout(cmd) do |io|
38 46 # Read svn version in first returned line
@@ -44,10 +52,10 module Redmine
44 52 version
45 53 end
46 54 end
47
55
48 56 # Get info about the svn repository
49 57 def info
50 cmd = "#{SVN_BIN} info --xml #{target}"
58 cmd = "#{self.class.sq_bin} info --xml #{target}"
51 59 cmd << credentials_string
52 60 info = nil
53 61 shellout(cmd) do |io|
@@ -70,14 +78,14 module Redmine
70 78 rescue CommandFailed
71 79 return nil
72 80 end
73
81
74 82 # Returns an Entries collection
75 83 # or nil if the given path doesn't exist in the repository
76 84 def entries(path=nil, identifier=nil)
77 85 path ||= ''
78 86 identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
79 87 entries = Entries.new
80 cmd = "#{SVN_BIN} list --xml #{target(path)}@#{identifier}"
88 cmd = "#{self.class.sq_bin} list --xml #{target(path)}@#{identifier}"
81 89 cmd << credentials_string
82 90 shellout(cmd) do |io|
83 91 output = io.read
@@ -110,13 +118,13 module Redmine
110 118 logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug?
111 119 entries.sort_by_name
112 120 end
113
121
114 122 def properties(path, identifier=nil)
115 123 # proplist xml output supported in svn 1.5.0 and higher
116 124 return nil unless self.class.client_version_above?([1, 5, 0])
117 125
118 126 identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
119 cmd = "#{SVN_BIN} proplist --verbose --xml #{target(path)}@#{identifier}"
127 cmd = "#{self.class.sq_bin} proplist --verbose --xml #{target(path)}@#{identifier}"
120 128 cmd << credentials_string
121 129 properties = {}
122 130 shellout(cmd) do |io|
@@ -132,13 +140,13 module Redmine
132 140 return nil if $? && $?.exitstatus != 0
133 141 properties
134 142 end
135
143
136 144 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
137 145 path ||= ''
138 146 identifier_from = (identifier_from && identifier_from.to_i > 0) ? identifier_from.to_i : "HEAD"
139 147 identifier_to = (identifier_to && identifier_to.to_i > 0) ? identifier_to.to_i : 1
140 148 revisions = Revisions.new
141 cmd = "#{SVN_BIN} log --xml -r #{identifier_from}:#{identifier_to}"
149 cmd = "#{self.class.sq_bin} log --xml -r #{identifier_from}:#{identifier_to}"
142 150 cmd << credentials_string
143 151 cmd << " --verbose " if options[:with_paths]
144 152 cmd << " --limit #{options[:limit].to_i}" if options[:limit]
@@ -171,13 +179,13 module Redmine
171 179 return nil if $? && $?.exitstatus != 0
172 180 revisions
173 181 end
174
182
175 183 def diff(path, identifier_from, identifier_to=nil, type="inline")
176 184 path ||= ''
177 185 identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : ''
178 186 identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : (identifier_from.to_i - 1)
179
180 cmd = "#{SVN_BIN} diff -r "
187
188 cmd = "#{self.class.sq_bin} diff -r "
181 189 cmd << "#{identifier_to}:"
182 190 cmd << "#{identifier_from}"
183 191 cmd << " #{target(path)}@#{identifier_from}"
@@ -191,10 +199,10 module Redmine
191 199 return nil if $? && $?.exitstatus != 0
192 200 diff
193 201 end
194
202
195 203 def cat(path, identifier=nil)
196 204 identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
197 cmd = "#{SVN_BIN} cat #{target(path)}@#{identifier}"
205 cmd = "#{self.class.sq_bin} cat #{target(path)}@#{identifier}"
198 206 cmd << credentials_string
199 207 cat = nil
200 208 shellout(cmd) do |io|
@@ -204,10 +212,10 module Redmine
204 212 return nil if $? && $?.exitstatus != 0
205 213 cat
206 214 end
207
215
208 216 def annotate(path, identifier=nil)
209 217 identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
210 cmd = "#{SVN_BIN} blame #{target(path)}@#{identifier}"
218 cmd = "#{self.class.sq_bin} blame #{target(path)}@#{identifier}"
211 219 cmd << credentials_string
212 220 blame = Annotate.new
213 221 shellout(cmd) do |io|
General Comments 0
You need to be logged in to leave comments. Login now