comparison lib/redmine/scm/adapters/.svn/text-base/bazaar_adapter.rb.svn-base @ 511:107d36338b70 live

Merge from branch "cannam"
author Chris Cannam
date Thu, 14 Jul 2011 10:43:07 +0100
parents cbce1fd3b1b7
children
comparison
equal deleted inserted replaced
451:a9f6345cb43d 511:107d36338b70
1 # redMine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 # 3 #
4 # This program is free software; you can redistribute it and/or 4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License 5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2 6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version. 7 # of the License, or (at your option) any later version.
8 # 8 #
9 # This program is distributed in the hope that it will be useful, 9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details. 12 # GNU General Public License for more details.
13 # 13 #
14 # You should have received a copy of the GNU General Public License 14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software 15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 require 'redmine/scm/adapters/abstract_adapter' 18 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 = "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
37 def client_version
38 @@client_version ||= (scm_command_version || [])
39 end
40
41 def client_available
42 !client_version.empty?
43 end
44
45 def scm_command_version
46 scm_version = scm_version_from_command_line.dup
47 if scm_version.respond_to?(:force_encoding)
48 scm_version.force_encoding('ASCII-8BIT')
49 end
50 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
51 m[2].scan(%r{\d+}).collect(&:to_i)
52 end
53 end
54
55 def scm_version_from_command_line
56 shellout("#{sq_bin} --version") { |io| io.read }.to_s
57 end
58 end
59
28 # Get info about the repository 60 # Get info about the repository
29 def info 61 def info
30 cmd = "#{BZR_BIN} revno #{target('')}" 62 cmd = "#{self.class.sq_bin} revno #{target('')}"
31 info = nil 63 info = nil
32 shellout(cmd) do |io| 64 shellout(cmd) do |io|
33 if io.read =~ %r{^(\d+)\r?$} 65 if io.read =~ %r{^(\d+)\r?$}
34 info = Info.new({:root_url => url, 66 info = Info.new({:root_url => url,
35 :lastrev => Revision.new({ 67 :lastrev => Revision.new({
41 return nil if $? && $?.exitstatus != 0 73 return nil if $? && $?.exitstatus != 0
42 info 74 info
43 rescue CommandFailed 75 rescue CommandFailed
44 return nil 76 return nil
45 end 77 end
46 78
47 # Returns an Entries collection 79 # Returns an Entries collection
48 # or nil if the given path doesn't exist in the repository 80 # or nil if the given path doesn't exist in the repository
49 def entries(path=nil, identifier=nil) 81 def entries(path=nil, identifier=nil, options={})
50 path ||= '' 82 path ||= ''
51 entries = Entries.new 83 entries = Entries.new
52 cmd = "#{BZR_BIN} ls -v --show-ids" 84 cmd = "#{self.class.sq_bin} ls -v --show-ids"
53 identifier = -1 unless identifier && identifier.to_i > 0 85 identifier = -1 unless identifier && identifier.to_i > 0
54 cmd << " -r#{identifier.to_i}" 86 cmd << " -r#{identifier.to_i}"
55 cmd << " #{target(path)}" 87 cmd << " #{target(path)}"
56 shellout(cmd) do |io| 88 shellout(cmd) do |io|
57 prefix = "#{url}/#{path}".gsub('\\', '/') 89 prefix = "#{url}/#{path}".gsub('\\', '/')
58 logger.debug "PREFIX: #{prefix}" 90 logger.debug "PREFIX: #{prefix}"
59 re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$} 91 re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
69 end 101 end
70 return nil if $? && $?.exitstatus != 0 102 return nil if $? && $?.exitstatus != 0
71 logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug? 103 logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug?
72 entries.sort_by_name 104 entries.sort_by_name
73 end 105 end
74 106
75 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) 107 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
76 path ||= '' 108 path ||= ''
77 identifier_from = 'last:1' unless identifier_from and identifier_from.to_i > 0 109 identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : 'last:1'
78 identifier_to = 1 unless identifier_to and identifier_to.to_i > 0 110 identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1
79 revisions = Revisions.new 111 revisions = Revisions.new
80 cmd = "#{BZR_BIN} log -v --show-ids -r#{identifier_to.to_i}..#{identifier_from} #{target(path)}" 112 cmd = "#{self.class.sq_bin} log -v --show-ids -r#{identifier_to}..#{identifier_from} #{target(path)}"
81 shellout(cmd) do |io| 113 shellout(cmd) do |io|
82 revision = nil 114 revision = nil
83 parsing = nil 115 parsing = nil
84 io.each_line do |line| 116 io.each_line do |line|
85 if line =~ /^----/ 117 if line =~ /^----/
86 revisions << revision if revision 118 revisions << revision if revision
87 revision = Revision.new(:paths => [], :message => '') 119 revision = Revision.new(:paths => [], :message => '')
88 parsing = nil 120 parsing = nil
89 else 121 else
90 next unless revision 122 next unless revision
91
92 if line =~ /^revno: (\d+)($|\s\[merge\]$)/ 123 if line =~ /^revno: (\d+)($|\s\[merge\]$)/
93 revision.identifier = $1.to_i 124 revision.identifier = $1.to_i
94 elsif line =~ /^committer: (.+)$/ 125 elsif line =~ /^committer: (.+)$/
95 revision.author = $1.strip 126 revision.author = $1.strip
96 elsif line =~ /^revision-id:(.+)$/ 127 elsif line =~ /^revision-id:(.+)$/
130 revisions << revision if revision 161 revisions << revision if revision
131 end 162 end
132 return nil if $? && $?.exitstatus != 0 163 return nil if $? && $?.exitstatus != 0
133 revisions 164 revisions
134 end 165 end
135 166
136 def diff(path, identifier_from, identifier_to=nil) 167 def diff(path, identifier_from, identifier_to=nil)
137 path ||= '' 168 path ||= ''
138 if identifier_to 169 if identifier_to
139 identifier_to = identifier_to.to_i 170 identifier_to = identifier_to.to_i
140 else 171 else
141 identifier_to = identifier_from.to_i - 1 172 identifier_to = identifier_from.to_i - 1
142 end 173 end
143 cmd = "#{BZR_BIN} diff -r#{identifier_to}..#{identifier_from} #{target(path)}" 174 if identifier_from
175 identifier_from = identifier_from.to_i
176 end
177 cmd = "#{self.class.sq_bin} diff -r#{identifier_to}..#{identifier_from} #{target(path)}"
144 diff = [] 178 diff = []
145 shellout(cmd) do |io| 179 shellout(cmd) do |io|
146 io.each_line do |line| 180 io.each_line do |line|
147 diff << line 181 diff << line
148 end 182 end
149 end 183 end
150 #return nil if $? && $?.exitstatus != 0 184 #return nil if $? && $?.exitstatus != 0
151 diff 185 diff
152 end 186 end
153 187
154 def cat(path, identifier=nil) 188 def cat(path, identifier=nil)
155 cmd = "#{BZR_BIN} cat" 189 cmd = "#{self.class.sq_bin} cat"
156 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0 190 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
157 cmd << " #{target(path)}" 191 cmd << " #{target(path)}"
158 cat = nil 192 cat = nil
159 shellout(cmd) do |io| 193 shellout(cmd) do |io|
160 io.binmode 194 io.binmode
161 cat = io.read 195 cat = io.read
162 end 196 end
163 return nil if $? && $?.exitstatus != 0 197 return nil if $? && $?.exitstatus != 0
164 cat 198 cat
165 end 199 end
166 200
167 def annotate(path, identifier=nil) 201 def annotate(path, identifier=nil)
168 cmd = "#{BZR_BIN} annotate --all" 202 cmd = "#{self.class.sq_bin} annotate --all"
169 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0 203 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
170 cmd << " #{target(path)}" 204 cmd << " #{target(path)}"
171 blame = Annotate.new 205 blame = Annotate.new
172 shellout(cmd) do |io| 206 shellout(cmd) do |io|
173 author = nil 207 author = nil
174 identifier = nil 208 identifier = nil
175 io.each_line do |line| 209 io.each_line do |line|
176 next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$} 210 next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$}
177 blame.add_line($3.rstrip, Revision.new(:identifier => $1.to_i, :author => $2.strip)) 211 rev = $1
212 blame.add_line($3.rstrip,
213 Revision.new(
214 :identifier => rev,
215 :revision => rev,
216 :author => $2.strip
217 ))
178 end 218 end
179 end 219 end
180 return nil if $? && $?.exitstatus != 0 220 return nil if $? && $?.exitstatus != 0
181 blame 221 blame
182 end 222 end