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