Revision 912:5e80956cc792 lib/redmine/scm/adapters
| lib/redmine/scm/adapters/abstract_adapter.rb | ||
|---|---|---|
| 24 | 24 |
end |
| 25 | 25 |
|
| 26 | 26 |
class AbstractAdapter #:nodoc: |
| 27 |
|
|
| 28 |
# raised if scm command exited with error, e.g. unknown revision. |
|
| 29 |
class ScmCommandAborted < CommandFailed; end |
|
| 30 |
|
|
| 27 | 31 |
class << self |
| 28 | 32 |
def client_command |
| 29 | 33 |
"" |
| 30 | 34 |
end |
| 31 | 35 |
|
| 36 |
def shell_quote_command |
|
| 37 |
if Redmine::Platform.mswin? && RUBY_PLATFORM == 'java' |
|
| 38 |
client_command |
|
| 39 |
else |
|
| 40 |
shell_quote(client_command) |
|
| 41 |
end |
|
| 42 |
end |
|
| 43 |
|
|
| 32 | 44 |
# Returns the version of the scm client |
| 33 | 45 |
# Eg: [1, 5, 0] or [] if unknown |
| 34 | 46 |
def client_version |
| ... | ... | |
| 180 | 192 |
info ? info.root_url : nil |
| 181 | 193 |
end |
| 182 | 194 |
|
| 183 |
def target(path) |
|
| 195 |
def target(path, sq=true)
|
|
| 184 | 196 |
path ||= '' |
| 185 | 197 |
base = path.match(/^\//) ? root_url : url |
| 186 |
shell_quote("#{base}/#{path}".gsub(/[?<>\*]/, ''))
|
|
| 198 |
str = "#{base}/#{path}".gsub(/[?<>\*]/, '')
|
|
| 199 |
if sq |
|
| 200 |
str = shell_quote(str) |
|
| 201 |
end |
|
| 202 |
str |
|
| 187 | 203 |
end |
| 188 | 204 |
|
| 189 | 205 |
def logger |
| ... | ... | |
| 195 | 211 |
end |
| 196 | 212 |
|
| 197 | 213 |
def self.logger |
| 198 |
RAILS_DEFAULT_LOGGER
|
|
| 214 |
Rails.logger
|
|
| 199 | 215 |
end |
| 200 | 216 |
|
| 201 | 217 |
def self.shellout(cmd, &block) |
| ... | ... | |
| 204 | 220 |
end |
| 205 | 221 |
if Rails.env == 'development' |
| 206 | 222 |
# Capture stderr when running in dev environment |
| 207 |
cmd = "#{cmd} 2>>#{RAILS_ROOT}/log/scm.stderr.log"
|
|
| 223 |
cmd = "#{cmd} 2>>#{Rails.root}/log/scm.stderr.log"
|
|
| 208 | 224 |
end |
| 209 | 225 |
begin |
| 210 | 226 |
if RUBY_VERSION < '1.9' |
| ... | ... | |
| 216 | 232 |
io.close_write |
| 217 | 233 |
block.call(io) if block_given? |
| 218 | 234 |
end |
| 219 |
rescue Errno::ENOENT => e |
|
| 235 |
## If scm command does not exist, |
|
| 236 |
## Linux JRuby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException |
|
| 237 |
## in production environment. |
|
| 238 |
# rescue Errno::ENOENT => e |
|
| 239 |
rescue Exception => e |
|
| 220 | 240 |
msg = strip_credential(e.message) |
| 221 | 241 |
# The command failed, log it and re-raise |
| 222 | 242 |
logmsg = "SCM command failed, " |
| ... | ... | |
| 313 | 333 |
|
| 314 | 334 |
class Revision |
| 315 | 335 |
attr_accessor :scmid, :name, :author, :time, :message, |
| 316 |
:paths, :revision, :branch, :identifier |
|
| 336 |
:paths, :revision, :branch, :identifier, |
|
| 337 |
:parents |
|
| 317 | 338 |
|
| 318 | 339 |
def initialize(attributes={})
|
| 319 | 340 |
self.identifier = attributes[:identifier] |
| ... | ... | |
| 325 | 346 |
self.paths = attributes[:paths] |
| 326 | 347 |
self.revision = attributes[:revision] |
| 327 | 348 |
self.branch = attributes[:branch] |
| 349 |
self.parents = attributes[:parents] |
|
| 328 | 350 |
end |
| 329 | 351 |
|
| 330 | 352 |
# Returns the readable identifier. |
| ... | ... | |
| 354 | 376 |
lines.empty? |
| 355 | 377 |
end |
| 356 | 378 |
end |
| 379 |
|
|
| 380 |
class Branch < String |
|
| 381 |
attr_accessor :revision, :scmid |
|
| 382 |
end |
|
| 357 | 383 |
end |
| 358 | 384 |
end |
| 359 | 385 |
end |
| lib/redmine/scm/adapters/bazaar_adapter.rb | ||
|---|---|---|
| 31 | 31 |
end |
| 32 | 32 |
|
| 33 | 33 |
def sq_bin |
| 34 |
@@sq_bin ||= shell_quote(BZR_BIN)
|
|
| 34 |
@@sq_bin ||= shell_quote_command
|
|
| 35 | 35 |
end |
| 36 | 36 |
|
| 37 | 37 |
def client_version |
| ... | ... | |
| 59 | 59 |
|
| 60 | 60 |
# Get info about the repository |
| 61 | 61 |
def info |
| 62 |
cmd = "#{self.class.sq_bin} revno #{target('')}"
|
|
| 62 |
cmd_args = %w|revno| |
|
| 63 |
cmd_args << bzr_target('')
|
|
| 63 | 64 |
info = nil |
| 64 |
shellout(cmd) do |io|
|
|
| 65 |
scm_cmd(*cmd_args) do |io|
|
|
| 65 | 66 |
if io.read =~ %r{^(\d+)\r?$}
|
| 66 | 67 |
info = Info.new({:root_url => url,
|
| 67 | 68 |
:lastrev => Revision.new({
|
| ... | ... | |
| 70 | 71 |
}) |
| 71 | 72 |
end |
| 72 | 73 |
end |
| 73 |
return nil if $? && $?.exitstatus != 0 |
|
| 74 | 74 |
info |
| 75 |
rescue CommandFailed
|
|
| 75 |
rescue ScmCommandAborted
|
|
| 76 | 76 |
return nil |
| 77 | 77 |
end |
| 78 | 78 |
|
| ... | ... | |
| 81 | 81 |
def entries(path=nil, identifier=nil, options={})
|
| 82 | 82 |
path ||= '' |
| 83 | 83 |
entries = Entries.new |
| 84 |
cmd = "#{self.class.sq_bin} ls -v --show-ids"
|
|
| 85 | 84 |
identifier = -1 unless identifier && identifier.to_i > 0 |
| 86 |
cmd << " -r#{identifier.to_i}"
|
|
| 87 |
cmd << " #{target(path)}"
|
|
| 88 |
shellout(cmd) do |io| |
|
| 85 |
cmd_args = %w|ls -v --show-ids| |
|
| 86 |
cmd_args << "-r#{identifier.to_i}"
|
|
| 87 |
cmd_args << bzr_target(path) |
|
| 88 |
scm_cmd(*cmd_args) do |io| |
|
| 89 | 89 |
prefix = "#{url}/#{path}".gsub('\\', '/')
|
| 90 | 90 |
logger.debug "PREFIX: #{prefix}"
|
| 91 | 91 |
re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
|
| ... | ... | |
| 99 | 99 |
}) |
| 100 | 100 |
end |
| 101 | 101 |
end |
| 102 |
return nil if $? && $?.exitstatus != 0 |
|
| 103 |
logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug?
|
|
| 102 |
if logger && logger.debug? |
|
| 103 |
logger.debug("Found #{entries.size} entries in the repository for #{target(path)}")
|
|
| 104 |
end |
|
| 104 | 105 |
entries.sort_by_name |
| 106 |
rescue ScmCommandAborted |
|
| 107 |
return nil |
|
| 105 | 108 |
end |
| 106 | 109 |
|
| 107 | 110 |
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
|
| ... | ... | |
| 109 | 112 |
identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : 'last:1' |
| 110 | 113 |
identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1 |
| 111 | 114 |
revisions = Revisions.new |
| 112 |
cmd = "#{self.class.sq_bin} log -v --show-ids -r#{identifier_to}..#{identifier_from} #{target(path)}"
|
|
| 113 |
shellout(cmd) do |io| |
|
| 115 |
cmd_args = %w|log -v --show-ids| |
|
| 116 |
cmd_args << "-r#{identifier_to}..#{identifier_from}"
|
|
| 117 |
cmd_args << bzr_target(path) |
|
| 118 |
scm_cmd(*cmd_args) do |io| |
|
| 114 | 119 |
revision = nil |
| 115 |
parsing = nil |
|
| 120 |
parsing = nil
|
|
| 116 | 121 |
io.each_line do |line| |
| 117 | 122 |
if line =~ /^----/ |
| 118 | 123 |
revisions << revision if revision |
| ... | ... | |
| 160 | 165 |
end |
| 161 | 166 |
revisions << revision if revision |
| 162 | 167 |
end |
| 163 |
return nil if $? && $?.exitstatus != 0 |
|
| 164 | 168 |
revisions |
| 169 |
rescue ScmCommandAborted |
|
| 170 |
return nil |
|
| 165 | 171 |
end |
| 166 | 172 |
|
| 167 | 173 |
def diff(path, identifier_from, identifier_to=nil) |
| ... | ... | |
| 174 | 180 |
if identifier_from |
| 175 | 181 |
identifier_from = identifier_from.to_i |
| 176 | 182 |
end |
| 177 |
cmd = "#{self.class.sq_bin} diff -r#{identifier_to}..#{identifier_from} #{target(path)}"
|
|
| 178 | 183 |
diff = [] |
| 179 |
shellout(cmd) do |io| |
|
| 184 |
cmd_args = %w|diff| |
|
| 185 |
cmd_args << "-r#{identifier_to}..#{identifier_from}"
|
|
| 186 |
cmd_args << bzr_target(path) |
|
| 187 |
scm_cmd_no_raise(*cmd_args) do |io| |
|
| 180 | 188 |
io.each_line do |line| |
| 181 | 189 |
diff << line |
| 182 | 190 |
end |
| 183 | 191 |
end |
| 184 |
#return nil if $? && $?.exitstatus != 0 |
|
| 185 | 192 |
diff |
| 186 | 193 |
end |
| 187 | 194 |
|
| 188 | 195 |
def cat(path, identifier=nil) |
| 189 |
cmd = "#{self.class.sq_bin} cat"
|
|
| 190 |
cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
|
|
| 191 |
cmd << " #{target(path)}"
|
|
| 192 | 196 |
cat = nil |
| 193 |
shellout(cmd) do |io| |
|
| 197 |
cmd_args = %w|cat| |
|
| 198 |
cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
|
|
| 199 |
cmd_args << bzr_target(path) |
|
| 200 |
scm_cmd(*cmd_args) do |io| |
|
| 194 | 201 |
io.binmode |
| 195 | 202 |
cat = io.read |
| 196 | 203 |
end |
| 197 |
return nil if $? && $?.exitstatus != 0 |
|
| 198 | 204 |
cat |
| 205 |
rescue ScmCommandAborted |
|
| 206 |
return nil |
|
| 199 | 207 |
end |
| 200 | 208 |
|
| 201 | 209 |
def annotate(path, identifier=nil) |
| 202 |
cmd = "#{self.class.sq_bin} annotate --all"
|
|
| 203 |
cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
|
|
| 204 |
cmd << " #{target(path)}"
|
|
| 205 | 210 |
blame = Annotate.new |
| 206 |
shellout(cmd) do |io| |
|
| 207 |
author = nil |
|
| 211 |
cmd_args = %w|annotate -q --all| |
|
| 212 |
cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
|
|
| 213 |
cmd_args << bzr_target(path) |
|
| 214 |
scm_cmd(*cmd_args) do |io| |
|
| 215 |
author = nil |
|
| 208 | 216 |
identifier = nil |
| 209 | 217 |
io.each_line do |line| |
| 210 | 218 |
next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$}
|
| ... | ... | |
| 217 | 225 |
)) |
| 218 | 226 |
end |
| 219 | 227 |
end |
| 220 |
return nil if $? && $?.exitstatus != 0 |
|
| 221 | 228 |
blame |
| 229 |
rescue ScmCommandAborted |
|
| 230 |
return nil |
|
| 222 | 231 |
end |
| 232 |
|
|
| 233 |
def self.branch_conf_path(path) |
|
| 234 |
bcp = nil |
|
| 235 |
m = path.match(%r{^(.*[/\\])\.bzr.*$})
|
|
| 236 |
if m |
|
| 237 |
bcp = m[1] |
|
| 238 |
else |
|
| 239 |
bcp = path |
|
| 240 |
end |
|
| 241 |
bcp.gsub!(%r{[\/\\]$}, "")
|
|
| 242 |
if bcp |
|
| 243 |
bcp = File.join(bcp, ".bzr", "branch", "branch.conf") |
|
| 244 |
end |
|
| 245 |
bcp |
|
| 246 |
end |
|
| 247 |
|
|
| 248 |
def append_revisions_only |
|
| 249 |
return @aro if ! @aro.nil? |
|
| 250 |
@aro = false |
|
| 251 |
bcp = self.class.branch_conf_path(url) |
|
| 252 |
if bcp && File.exist?(bcp) |
|
| 253 |
begin |
|
| 254 |
f = File::open(bcp, "r") |
|
| 255 |
cnt = 0 |
|
| 256 |
f.each_line do |line| |
|
| 257 |
l = line.chomp.to_s |
|
| 258 |
if l =~ /^\s*append_revisions_only\s*=\s*(\w+)\s*$/ |
|
| 259 |
str_aro = $1 |
|
| 260 |
if str_aro.upcase == "TRUE" |
|
| 261 |
@aro = true |
|
| 262 |
cnt += 1 |
|
| 263 |
elsif str_aro.upcase == "FALSE" |
|
| 264 |
@aro = false |
|
| 265 |
cnt += 1 |
|
| 266 |
end |
|
| 267 |
if cnt > 1 |
|
| 268 |
@aro = false |
|
| 269 |
break |
|
| 270 |
end |
|
| 271 |
end |
|
| 272 |
end |
|
| 273 |
ensure |
|
| 274 |
f.close |
|
| 275 |
end |
|
| 276 |
end |
|
| 277 |
@aro |
|
| 278 |
end |
|
| 279 |
|
|
| 280 |
def scm_cmd(*args, &block) |
|
| 281 |
full_args = [] |
|
| 282 |
full_args += args |
|
| 283 |
ret = shellout( |
|
| 284 |
self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
|
|
| 285 |
&block |
|
| 286 |
) |
|
| 287 |
if $? && $?.exitstatus != 0 |
|
| 288 |
raise ScmCommandAborted, "bzr exited with non-zero status: #{$?.exitstatus}"
|
|
| 289 |
end |
|
| 290 |
ret |
|
| 291 |
end |
|
| 292 |
private :scm_cmd |
|
| 293 |
|
|
| 294 |
def scm_cmd_no_raise(*args, &block) |
|
| 295 |
full_args = [] |
|
| 296 |
full_args += args |
|
| 297 |
ret = shellout( |
|
| 298 |
self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
|
|
| 299 |
&block |
|
| 300 |
) |
|
| 301 |
ret |
|
| 302 |
end |
|
| 303 |
private :scm_cmd_no_raise |
|
| 304 |
|
|
| 305 |
def bzr_target(path) |
|
| 306 |
target(path, false) |
|
| 307 |
end |
|
| 308 |
private :bzr_target |
|
| 223 | 309 |
end |
| 224 | 310 |
end |
| 225 | 311 |
end |
| lib/redmine/scm/adapters/cvs_adapter.rb | ||
|---|---|---|
| 25 | 25 |
# CVS executable name |
| 26 | 26 |
CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs" |
| 27 | 27 |
|
| 28 |
# raised if scm command exited with error, e.g. unknown revision. |
|
| 29 |
class ScmCommandAborted < CommandFailed; end |
|
| 30 |
|
|
| 31 | 28 |
class << self |
| 32 | 29 |
def client_command |
| 33 | 30 |
@@bin ||= CVS_BIN |
| 34 | 31 |
end |
| 35 | 32 |
|
| 36 | 33 |
def sq_bin |
| 37 |
@@sq_bin ||= shell_quote(CVS_BIN)
|
|
| 34 |
@@sq_bin ||= shell_quote_command
|
|
| 38 | 35 |
end |
| 39 | 36 |
|
| 40 | 37 |
def client_version |
| ... | ... | |
| 379 | 376 |
end |
| 380 | 377 |
|
| 381 | 378 |
def scm_cmd(*args, &block) |
| 382 |
full_args = [CVS_BIN, '-d', root_url]
|
|
| 379 |
full_args = ['-d', root_url] |
|
| 383 | 380 |
full_args += args |
| 384 | 381 |
full_args_locale = [] |
| 385 | 382 |
full_args.map do |e| |
| 386 | 383 |
full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e) |
| 387 | 384 |
end |
| 388 |
ret = shellout(full_args_locale.map { |e| shell_quote e.to_s }.join(' '), &block)
|
|
| 385 |
ret = shellout( |
|
| 386 |
self.class.sq_bin + ' ' + full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
|
|
| 387 |
&block |
|
| 388 |
) |
|
| 389 | 389 |
if $? && $?.exitstatus != 0 |
| 390 | 390 |
raise ScmCommandAborted, "cvs exited with non-zero status: #{$?.exitstatus}"
|
| 391 | 391 |
end |
| lib/redmine/scm/adapters/darcs_adapter.rb | ||
|---|---|---|
| 31 | 31 |
end |
| 32 | 32 |
|
| 33 | 33 |
def sq_bin |
| 34 |
@@sq_bin ||= shell_quote(DARCS_BIN)
|
|
| 34 |
@@sq_bin ||= shell_quote_command
|
|
| 35 | 35 |
end |
| 36 | 36 |
|
| 37 | 37 |
def client_version |
| lib/redmine/scm/adapters/git_adapter.rb | ||
|---|---|---|
| 25 | 25 |
# Git executable name |
| 26 | 26 |
GIT_BIN = Redmine::Configuration['scm_git_command'] || "git" |
| 27 | 27 |
|
| 28 |
# raised if scm command exited with error, e.g. unknown revision. |
|
| 29 |
class ScmCommandAborted < CommandFailed; end |
|
| 30 |
|
|
| 31 | 28 |
class << self |
| 32 | 29 |
def client_command |
| 33 | 30 |
@@bin ||= GIT_BIN |
| 34 | 31 |
end |
| 35 | 32 |
|
| 36 | 33 |
def sq_bin |
| 37 |
@@sq_bin ||= shell_quote(GIT_BIN)
|
|
| 34 |
@@sq_bin ||= shell_quote_command
|
|
| 38 | 35 |
end |
| 39 | 36 |
|
| 40 | 37 |
def client_version |
| ... | ... | |
| 80 | 77 |
def branches |
| 81 | 78 |
return @branches if @branches |
| 82 | 79 |
@branches = [] |
| 83 |
cmd_args = %w|branch --no-color| |
|
| 80 |
cmd_args = %w|branch --no-color --verbose --no-abbrev|
|
|
| 84 | 81 |
scm_cmd(*cmd_args) do |io| |
| 85 | 82 |
io.each_line do |line| |
| 86 |
@branches << line.match('\s*\*?\s*(.*)$')[1]
|
|
| 83 |
branch_rev = line.match('\s*\*?\s*(.*?)\s*([0-9a-f]{40}).*$')
|
|
| 84 |
bran = Branch.new(branch_rev[1]) |
|
| 85 |
bran.revision = branch_rev[2] |
|
| 86 |
bran.scmid = branch_rev[2] |
|
| 87 |
@branches << bran |
|
| 87 | 88 |
end |
| 88 | 89 |
end |
| 89 | 90 |
@branches.sort! |
| ... | ... | |
| 188 | 189 |
|
| 189 | 190 |
def revisions(path, identifier_from, identifier_to, options={})
|
| 190 | 191 |
revs = Revisions.new |
| 191 |
cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller| |
|
| 192 |
cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents|
|
|
| 192 | 193 |
cmd_args << "--reverse" if options[:reverse] |
| 193 | 194 |
cmd_args << "--all" if options[:all] |
| 194 | 195 |
cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
|
| ... | ... | |
| 205 | 206 |
parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files |
| 206 | 207 |
|
| 207 | 208 |
io.each_line do |line| |
| 208 |
if line =~ /^commit ([0-9a-f]{40})$/
|
|
| 209 |
if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/
|
|
| 209 | 210 |
key = "commit" |
| 210 | 211 |
value = $1 |
| 212 |
parents_str = $2 |
|
| 211 | 213 |
if (parsing_descr == 1 || parsing_descr == 2) |
| 212 | 214 |
parsing_descr = 0 |
| 213 | 215 |
revision = Revision.new({
|
| ... | ... | |
| 216 | 218 |
:author => changeset[:author], |
| 217 | 219 |
:time => Time.parse(changeset[:date]), |
| 218 | 220 |
:message => changeset[:description], |
| 219 |
:paths => files |
|
| 221 |
:paths => files, |
|
| 222 |
:parents => changeset[:parents] |
|
| 220 | 223 |
}) |
| 221 | 224 |
if block_given? |
| 222 | 225 |
yield revision |
| ... | ... | |
| 227 | 230 |
files = [] |
| 228 | 231 |
end |
| 229 | 232 |
changeset[:commit] = $1 |
| 233 |
unless parents_str.nil? or parents_str == "" |
|
| 234 |
changeset[:parents] = parents_str.strip.split(' ')
|
|
| 235 |
end |
|
| 230 | 236 |
elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/ |
| 231 | 237 |
key = $1 |
| 232 | 238 |
value = $2 |
| ... | ... | |
| 266 | 272 |
:author => changeset[:author], |
| 267 | 273 |
:time => Time.parse(changeset[:date]), |
| 268 | 274 |
:message => changeset[:description], |
| 269 |
:paths => files |
|
| 275 |
:paths => files, |
|
| 276 |
:parents => changeset[:parents] |
|
| 270 | 277 |
}) |
| 271 | 278 |
if block_given? |
| 272 | 279 |
yield revision |
| ... | ... | |
| 359 | 366 |
|
| 360 | 367 |
def scm_cmd(*args, &block) |
| 361 | 368 |
repo_path = root_url || url |
| 362 |
full_args = [GIT_BIN, '--git-dir', repo_path]
|
|
| 369 |
full_args = ['--git-dir', repo_path] |
|
| 363 | 370 |
if self.class.client_version_above?([1, 7, 2]) |
| 364 | 371 |
full_args << '-c' << 'core.quotepath=false' |
| 365 | 372 |
full_args << '-c' << 'log.decorate=no' |
| 366 | 373 |
end |
| 367 | 374 |
full_args += args |
| 368 |
ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block)
|
|
| 375 |
ret = shellout( |
|
| 376 |
self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
|
|
| 377 |
&block |
|
| 378 |
) |
|
| 369 | 379 |
if $? && $?.exitstatus != 0 |
| 370 | 380 |
raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}"
|
| 371 | 381 |
end |
| lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl | ||
|---|---|---|
| 1 | 1 |
changeset = 'This template must be used with --debug option\n' |
| 2 | 2 |
changeset_quiet = 'This template must be used with --debug option\n' |
| 3 | 3 |
changeset_verbose = 'This template must be used with --debug option\n' |
| 4 |
changeset_debug = '<logentry revision="{rev}" node="{node|short}">\n<author>{author|escape}</author>\n<date>{date|isodatesec}</date>\n<paths>\n{file_mods}{file_adds}{file_dels}{file_copies}</paths>\n<msg>{desc|escape}</msg>\n{tags}</logentry>\n\n'
|
|
| 4 |
changeset_debug = '<logentry revision="{rev}" node="{node|short}">\n<author>{author|escape}</author>\n<date>{date|isodatesec}</date>\n<paths>\n{file_mods}{file_adds}{file_dels}{file_copies}</paths>\n<msg>{desc|escape}</msg>\n<parents>\n{parents}</parents>\n</logentry>\n\n'
|
|
| 5 | 5 |
|
| 6 | 6 |
file_mod = '<path action="M">{file_mod|urlescape}</path>\n'
|
| 7 | 7 |
file_add = '<path action="A">{file_add|urlescape}</path>\n'
|
| 8 | 8 |
file_del = '<path action="D">{file_del|urlescape}</path>\n'
|
| 9 | 9 |
file_copy = '<path-copied copyfrom-path="{source|urlescape}">{name|urlescape}</path-copied>\n'
|
| 10 |
tag = '<tag>{tag|escape}</tag>\n'
|
|
| 10 |
parent = '<parent>{node|short}</parent>\n'
|
|
| 11 | 11 |
header='<?xml version="1.0" encoding="UTF-8" ?>\n<log>\n\n' |
| 12 | 12 |
footer='</log>' |
| lib/redmine/scm/adapters/mercurial/redminehelper.py | ||
|---|---|---|
| 46 | 46 |
</rhmanifest> |
| 47 | 47 |
""" |
| 48 | 48 |
import re, time, cgi, urllib |
| 49 |
from mercurial import cmdutil, commands, node, error |
|
| 49 |
from mercurial import cmdutil, commands, node, error, hg
|
|
| 50 | 50 |
|
| 51 | 51 |
_x = cgi.escape |
| 52 | 52 |
_u = lambda s: cgi.escape(urllib.quote(s)) |
| ... | ... | |
| 146 | 146 |
bra = urllib.unquote_plus(opts.pop('rhbranch', None))
|
| 147 | 147 |
from_rev = from_rev.replace('"', '\\"')
|
| 148 | 148 |
to_rev = to_rev.replace('"', '\\"')
|
| 149 |
opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)] |
|
| 149 |
if hg.util.version() >= '1.6': |
|
| 150 |
opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)] |
|
| 151 |
else: |
|
| 152 |
opts['rev'] = ['%s:%s' % (from_rev, to_rev)] |
|
| 150 | 153 |
opts['branch'] = [bra] |
| 151 | 154 |
return commands.log(ui, repo, *map(urllib.unquote_plus, pats), **opts) |
| 152 | 155 |
|
| ... | ... | |
| 196 | 199 |
[ |
| 197 | 200 |
('r', 'rev', [], 'show the specified revision'),
|
| 198 | 201 |
('b', 'branch', [],
|
| 199 |
'show changesets within the given named branch', 'BRANCH'),
|
|
| 202 |
'show changesets within the given named branch'), |
|
| 200 | 203 |
('l', 'limit', '',
|
| 201 |
'limit number of changes displayed', 'NUM'),
|
|
| 204 |
'limit number of changes displayed'), |
|
| 202 | 205 |
('d', 'date', '',
|
| 203 |
'show revisions matching date spec', 'DATE'),
|
|
| 206 |
'show revisions matching date spec'), |
|
| 204 | 207 |
('u', 'user', [],
|
| 205 |
'revisions committed by user', 'USER'),
|
|
| 208 |
'revisions committed by user'), |
|
| 206 | 209 |
('', 'from', '',
|
| 207 |
'', ''),
|
|
| 210 |
''), |
|
| 208 | 211 |
('', 'to', '',
|
| 209 |
'', ''),
|
|
| 212 |
''), |
|
| 210 | 213 |
('', 'rhbranch', '',
|
| 211 |
'', ''),
|
|
| 214 |
''), |
|
| 212 | 215 |
('', 'template', '',
|
| 213 |
'display with template', 'TEMPLATE')],
|
|
| 216 |
'display with template')], |
|
| 214 | 217 |
'hg rhlog [OPTION]... [FILE]'), |
| 215 | 218 |
'rhmanifest': (rhmanifest, |
| 216 | 219 |
[('r', 'rev', '', 'show the specified revision')],
|
| lib/redmine/scm/adapters/mercurial_adapter.rb | ||
|---|---|---|
| 39 | 39 |
end |
| 40 | 40 |
|
| 41 | 41 |
def sq_bin |
| 42 |
@@sq_bin ||= shell_quote(HG_BIN)
|
|
| 42 |
@@sq_bin ||= shell_quote_command
|
|
| 43 | 43 |
end |
| 44 | 44 |
|
| 45 | 45 |
def client_version |
| ... | ... | |
| 47 | 47 |
end |
| 48 | 48 |
|
| 49 | 49 |
def client_available |
| 50 |
client_version_above?([0, 9, 5])
|
|
| 50 |
client_version_above?([1, 2])
|
|
| 51 | 51 |
end |
| 52 | 52 |
|
| 53 | 53 |
def hgversion |
| ... | ... | |
| 72 | 72 |
end |
| 73 | 73 |
|
| 74 | 74 |
def template_path_for(version) |
| 75 |
if ((version <=> [0,9,5]) > 0) || version.empty? |
|
| 76 |
ver = "1.0" |
|
| 77 |
else |
|
| 78 |
ver = "0.9.5" |
|
| 79 |
end |
|
| 80 |
"#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{ver}.#{TEMPLATE_EXTENSION}"
|
|
| 75 |
"#{HELPERS_DIR}/#{TEMPLATE_NAME}-1.0.#{TEMPLATE_EXTENSION}"
|
|
| 81 | 76 |
end |
| 82 | 77 |
end |
| 83 | 78 |
|
| ... | ... | |
| 114 | 109 |
end |
| 115 | 110 |
|
| 116 | 111 |
def branches |
| 117 |
as_ary(summary['repository']['branch']).map { |e| e['name'] }
|
|
| 112 |
brs = [] |
|
| 113 |
as_ary(summary['repository']['branch']).each do |e| |
|
| 114 |
br = Branch.new(e['name']) |
|
| 115 |
br.revision = e['revision'] |
|
| 116 |
br.scmid = e['node'] |
|
| 117 |
brs << br |
|
| 118 |
end |
|
| 119 |
brs |
|
| 118 | 120 |
end |
| 119 | 121 |
|
| 120 | 122 |
# Returns map of {'branch' => 'nodeid', ...}
|
| ... | ... | |
| 214 | 216 |
:from_path => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil), |
| 215 | 217 |
:from_revision => (cpmap.member?(p) ? le['node'] : nil)} |
| 216 | 218 |
end.sort { |a, b| a[:path] <=> b[:path] }
|
| 219 |
parents_ary = [] |
|
| 220 |
as_ary(le['parents']['parent']).map do |par| |
|
| 221 |
parents_ary << par['__content__'] if par['__content__'] != "000000000000" |
|
| 222 |
end |
|
| 217 | 223 |
yield Revision.new(:revision => le['revision'], |
| 218 | 224 |
:scmid => le['node'], |
| 219 | 225 |
:author => (le['author']['__content__'] rescue ''), |
| 220 | 226 |
:time => Time.parse(le['date']['__content__']), |
| 221 | 227 |
:message => le['msg']['__content__'], |
| 222 |
:paths => paths) |
|
| 228 |
:paths => paths, |
|
| 229 |
:parents => parents_ary) |
|
| 223 | 230 |
end |
| 224 | 231 |
self |
| 225 | 232 |
end |
| ... | ... | |
| 293 | 300 |
# Runs 'hg' command with the given args |
| 294 | 301 |
def hg(*args, &block) |
| 295 | 302 |
repo_path = root_url || url |
| 296 |
full_args = [HG_BIN, '-R', repo_path, '--encoding', 'utf-8']
|
|
| 303 |
full_args = ['-R', repo_path, '--encoding', 'utf-8'] |
|
| 297 | 304 |
full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}"
|
| 298 | 305 |
full_args << '--config' << 'diff.git=false' |
| 299 | 306 |
full_args += args |
| 300 |
ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block)
|
|
| 307 |
ret = shellout( |
|
| 308 |
self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
|
|
| 309 |
&block |
|
| 310 |
) |
|
| 301 | 311 |
if $? && $?.exitstatus != 0 |
| 302 | 312 |
raise HgCommandAborted, "hg exited with non-zero status: #{$?.exitstatus}"
|
| 303 | 313 |
end |
| lib/redmine/scm/adapters/mercurial_adapter.rb.rej | ||
|---|---|---|
| 1 |
--- lib/redmine/scm/adapters/mercurial_adapter.rb |
|
| 2 |
+++ lib/redmine/scm/adapters/mercurial_adapter.rb |
|
| 3 |
@@ -67,19 +67,17 @@ |
|
| 4 |
end |
|
| 5 |
|
|
| 6 |
def info |
|
| 7 |
- cmd = "#{HG_BIN} -R #{target('')} root"
|
|
| 8 |
- root_url = nil |
|
| 9 |
- shellout(cmd) do |io| |
|
| 10 |
- root_url = io.gets |
|
| 11 |
- end |
|
| 12 |
- return nil if $? && $?.exitstatus != 0 |
|
| 13 |
- info = Info.new({:root_url => root_url.chomp,
|
|
| 14 |
- :lastrev => revisions(nil,nil,nil,{:limit => 1}).last
|
|
| 15 |
- }) |
|
| 16 |
- info |
|
| 17 |
- rescue CommandFailed |
|
| 18 |
- return nil |
|
| 19 |
+ tip = summary['tip'].first |
|
| 20 |
+ Info.new(:root_url => summary['root'].first['path'], |
|
| 21 |
+ :lastrev => Revision.new(:identifier => tip['rev'].to_i, |
|
| 22 |
+ :revision => tip['rev'], |
|
| 23 |
+ :scmid => tip['node'])) |
|
| 24 |
end |
|
| 25 |
+ |
|
| 26 |
+ def summary |
|
| 27 |
+ @summary ||= fetchg 'rhsummary' |
|
| 28 |
+ end |
|
| 29 |
+ private :summary |
|
| 30 |
|
|
| 31 |
def entries(path=nil, identifier=nil) |
|
| 32 |
path ||= '' |
|
| 33 |
--- lib/redmine/scm/adapters/mercurial_adapter.rb |
|
| 34 |
+++ lib/redmine/scm/adapters/mercurial_adapter.rb |
|
| 35 |
@@ -74,6 +74,16 @@ |
|
| 36 |
:scmid => tip['node'])) |
|
| 37 |
end |
|
| 38 |
|
|
| 39 |
+ def tags |
|
| 40 |
+ summary['tags'].map { |e| e['name'] }
|
|
| 41 |
+ end |
|
| 42 |
+ |
|
| 43 |
+ # Returns map of {'tag' => 'nodeid', ...}
|
|
| 44 |
+ def tagmap |
|
| 45 |
+ alist = summary['tags'].map { |e| e.values_at('name', 'node') }
|
|
| 46 |
+ Hash[*alist.flatten] |
|
| 47 |
+ end |
|
| 48 |
+ |
|
| 49 |
def summary |
|
| 50 |
@summary ||= fetchg 'rhsummary' |
|
| 51 |
end |
|
| 52 |
--- lib/redmine/scm/adapters/mercurial_adapter.rb |
|
| 53 |
+++ lib/redmine/scm/adapters/mercurial_adapter.rb |
|
| 54 |
@@ -84,6 +84,19 @@ |
|
| 55 |
Hash[*alist.flatten] |
|
| 56 |
end |
|
| 57 |
|
|
| 58 |
+ def branches |
|
| 59 |
+ summary['branches'].map { |e| e['name'] }
|
|
| 60 |
+ end |
|
| 61 |
+ |
|
| 62 |
+ # Returns map of {'branch' => 'nodeid', ...}
|
|
| 63 |
+ def branchmap |
|
| 64 |
+ alist = summary['branches'].map { |e| e.values_at('name', 'node') }
|
|
| 65 |
+ Hash[*alist.flatten] |
|
| 66 |
+ end |
|
| 67 |
+ |
|
| 68 |
+ # NOTE: DO NOT IMPLEMENT default_branch !! |
|
| 69 |
+ # It's used as the default revision by RepositoriesController. |
|
| 70 |
+ |
|
| 71 |
def summary |
|
| 72 |
@summary ||= fetchg 'rhsummary' |
|
| 73 |
end |
|
| lib/redmine/scm/adapters/subversion_adapter.rb | ||
|---|---|---|
| 32 | 32 |
end |
| 33 | 33 |
|
| 34 | 34 |
def sq_bin |
| 35 |
@@sq_bin ||= shell_quote(SVN_BIN)
|
|
| 35 |
@@sq_bin ||= shell_quote_command
|
|
| 36 | 36 |
end |
| 37 | 37 |
|
| 38 | 38 |
def client_version |
Also available in: Unified diff