##// END OF EJS Templates
scm: git: explicitly return string as default branch (#10207)...
Toshi MARUYAMA -
r8737:58996e891ef7
parent child
Show More
@@ -1,406 +1,407
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 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 GitAdapter < AbstractAdapter
23 class GitAdapter < AbstractAdapter
24
24
25 # Git executable name
25 # Git executable name
26 GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
26 GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
27
27
28 class GitBranch < Branch
28 class GitBranch < Branch
29 attr_accessor :is_default
29 attr_accessor :is_default
30 end
30 end
31
31
32 class << self
32 class << self
33 def client_command
33 def client_command
34 @@bin ||= GIT_BIN
34 @@bin ||= GIT_BIN
35 end
35 end
36
36
37 def sq_bin
37 def sq_bin
38 @@sq_bin ||= shell_quote_command
38 @@sq_bin ||= shell_quote_command
39 end
39 end
40
40
41 def client_version
41 def client_version
42 @@client_version ||= (scm_command_version || [])
42 @@client_version ||= (scm_command_version || [])
43 end
43 end
44
44
45 def client_available
45 def client_available
46 !client_version.empty?
46 !client_version.empty?
47 end
47 end
48
48
49 def scm_command_version
49 def scm_command_version
50 scm_version = scm_version_from_command_line.dup
50 scm_version = scm_version_from_command_line.dup
51 if scm_version.respond_to?(:force_encoding)
51 if scm_version.respond_to?(:force_encoding)
52 scm_version.force_encoding('ASCII-8BIT')
52 scm_version.force_encoding('ASCII-8BIT')
53 end
53 end
54 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
54 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
55 m[2].scan(%r{\d+}).collect(&:to_i)
55 m[2].scan(%r{\d+}).collect(&:to_i)
56 end
56 end
57 end
57 end
58
58
59 def scm_version_from_command_line
59 def scm_version_from_command_line
60 shellout("#{sq_bin} --version --no-color") { |io| io.read }.to_s
60 shellout("#{sq_bin} --version --no-color") { |io| io.read }.to_s
61 end
61 end
62 end
62 end
63
63
64 def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
64 def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
65 super
65 super
66 @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
66 @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
67 end
67 end
68
68
69 def path_encoding
69 def path_encoding
70 @path_encoding
70 @path_encoding
71 end
71 end
72
72
73 def info
73 def info
74 begin
74 begin
75 Info.new(:root_url => url, :lastrev => lastrev('',nil))
75 Info.new(:root_url => url, :lastrev => lastrev('',nil))
76 rescue
76 rescue
77 nil
77 nil
78 end
78 end
79 end
79 end
80
80
81 def branches
81 def branches
82 return @branches if @branches
82 return @branches if @branches
83 @branches = []
83 @branches = []
84 cmd_args = %w|branch --no-color --verbose --no-abbrev|
84 cmd_args = %w|branch --no-color --verbose --no-abbrev|
85 scm_cmd(*cmd_args) do |io|
85 scm_cmd(*cmd_args) do |io|
86 io.each_line do |line|
86 io.each_line do |line|
87 branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
87 branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
88 bran = GitBranch.new(branch_rev[2])
88 bran = GitBranch.new(branch_rev[2])
89 bran.revision = branch_rev[3]
89 bran.revision = branch_rev[3]
90 bran.scmid = branch_rev[3]
90 bran.scmid = branch_rev[3]
91 bran.is_default = ( branch_rev[1] == '*' )
91 bran.is_default = ( branch_rev[1] == '*' )
92 @branches << bran
92 @branches << bran
93 end
93 end
94 end
94 end
95 @branches.sort!
95 @branches.sort!
96 rescue ScmCommandAborted
96 rescue ScmCommandAborted
97 nil
97 nil
98 end
98 end
99
99
100 def tags
100 def tags
101 return @tags if @tags
101 return @tags if @tags
102 cmd_args = %w|tag|
102 cmd_args = %w|tag|
103 scm_cmd(*cmd_args) do |io|
103 scm_cmd(*cmd_args) do |io|
104 @tags = io.readlines.sort!.map{|t| t.strip}
104 @tags = io.readlines.sort!.map{|t| t.strip}
105 end
105 end
106 rescue ScmCommandAborted
106 rescue ScmCommandAborted
107 nil
107 nil
108 end
108 end
109
109
110 def default_branch
110 def default_branch
111 bras = self.branches
111 bras = self.branches
112 return nil if bras.nil?
112 return nil if bras.nil?
113 default_bras = bras.select{|x| x.is_default == true}
113 default_bras = bras.select{|x| x.is_default == true}
114 return default_bras.first if ! default_bras.empty?
114 return default_bras.first.to_s if ! default_bras.empty?
115 bras.include?('master') ? 'master' : bras.first
115 master_bras = bras.select{|x| x.to_s == 'master'}
116 master_bras.empty? ? bras.first.to_s : 'master'
116 end
117 end
117
118
118 def entry(path=nil, identifier=nil)
119 def entry(path=nil, identifier=nil)
119 parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
120 parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
120 search_path = parts[0..-2].join('/')
121 search_path = parts[0..-2].join('/')
121 search_name = parts[-1]
122 search_name = parts[-1]
122 if search_path.blank? && search_name.blank?
123 if search_path.blank? && search_name.blank?
123 # Root entry
124 # Root entry
124 Entry.new(:path => '', :kind => 'dir')
125 Entry.new(:path => '', :kind => 'dir')
125 else
126 else
126 # Search for the entry in the parent directory
127 # Search for the entry in the parent directory
127 es = entries(search_path, identifier,
128 es = entries(search_path, identifier,
128 options = {:report_last_commit => false})
129 options = {:report_last_commit => false})
129 es ? es.detect {|e| e.name == search_name} : nil
130 es ? es.detect {|e| e.name == search_name} : nil
130 end
131 end
131 end
132 end
132
133
133 def entries(path=nil, identifier=nil, options={})
134 def entries(path=nil, identifier=nil, options={})
134 path ||= ''
135 path ||= ''
135 p = scm_iconv(@path_encoding, 'UTF-8', path)
136 p = scm_iconv(@path_encoding, 'UTF-8', path)
136 entries = Entries.new
137 entries = Entries.new
137 cmd_args = %w|ls-tree -l|
138 cmd_args = %w|ls-tree -l|
138 cmd_args << "HEAD:#{p}" if identifier.nil?
139 cmd_args << "HEAD:#{p}" if identifier.nil?
139 cmd_args << "#{identifier}:#{p}" if identifier
140 cmd_args << "#{identifier}:#{p}" if identifier
140 scm_cmd(*cmd_args) do |io|
141 scm_cmd(*cmd_args) do |io|
141 io.each_line do |line|
142 io.each_line do |line|
142 e = line.chomp.to_s
143 e = line.chomp.to_s
143 if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/
144 if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/
144 type = $1
145 type = $1
145 sha = $2
146 sha = $2
146 size = $3
147 size = $3
147 name = $4
148 name = $4
148 if name.respond_to?(:force_encoding)
149 if name.respond_to?(:force_encoding)
149 name.force_encoding(@path_encoding)
150 name.force_encoding(@path_encoding)
150 end
151 end
151 full_path = p.empty? ? name : "#{p}/#{name}"
152 full_path = p.empty? ? name : "#{p}/#{name}"
152 n = scm_iconv('UTF-8', @path_encoding, name)
153 n = scm_iconv('UTF-8', @path_encoding, name)
153 full_p = scm_iconv('UTF-8', @path_encoding, full_path)
154 full_p = scm_iconv('UTF-8', @path_encoding, full_path)
154 entries << Entry.new({:name => n,
155 entries << Entry.new({:name => n,
155 :path => full_p,
156 :path => full_p,
156 :kind => (type == "tree") ? 'dir' : 'file',
157 :kind => (type == "tree") ? 'dir' : 'file',
157 :size => (type == "tree") ? nil : size,
158 :size => (type == "tree") ? nil : size,
158 :lastrev => options[:report_last_commit] ?
159 :lastrev => options[:report_last_commit] ?
159 lastrev(full_path, identifier) : Revision.new
160 lastrev(full_path, identifier) : Revision.new
160 }) unless entries.detect{|entry| entry.name == name}
161 }) unless entries.detect{|entry| entry.name == name}
161 end
162 end
162 end
163 end
163 end
164 end
164 entries.sort_by_name
165 entries.sort_by_name
165 rescue ScmCommandAborted
166 rescue ScmCommandAborted
166 nil
167 nil
167 end
168 end
168
169
169 def lastrev(path, rev)
170 def lastrev(path, rev)
170 return nil if path.nil?
171 return nil if path.nil?
171 cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
172 cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
172 cmd_args << rev if rev
173 cmd_args << rev if rev
173 cmd_args << "--" << path unless path.empty?
174 cmd_args << "--" << path unless path.empty?
174 lines = []
175 lines = []
175 scm_cmd(*cmd_args) { |io| lines = io.readlines }
176 scm_cmd(*cmd_args) { |io| lines = io.readlines }
176 begin
177 begin
177 id = lines[0].split[1]
178 id = lines[0].split[1]
178 author = lines[1].match('Author:\s+(.*)$')[1]
179 author = lines[1].match('Author:\s+(.*)$')[1]
179 time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1])
180 time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1])
180
181
181 Revision.new({
182 Revision.new({
182 :identifier => id,
183 :identifier => id,
183 :scmid => id,
184 :scmid => id,
184 :author => author,
185 :author => author,
185 :time => time,
186 :time => time,
186 :message => nil,
187 :message => nil,
187 :paths => nil
188 :paths => nil
188 })
189 })
189 rescue NoMethodError => e
190 rescue NoMethodError => e
190 logger.error("The revision '#{path}' has a wrong format")
191 logger.error("The revision '#{path}' has a wrong format")
191 return nil
192 return nil
192 end
193 end
193 rescue ScmCommandAborted
194 rescue ScmCommandAborted
194 nil
195 nil
195 end
196 end
196
197
197 def revisions(path, identifier_from, identifier_to, options={})
198 def revisions(path, identifier_from, identifier_to, options={})
198 revs = Revisions.new
199 revs = Revisions.new
199 cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents|
200 cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents|
200 cmd_args << "--reverse" if options[:reverse]
201 cmd_args << "--reverse" if options[:reverse]
201 cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
202 cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
202 from_to = ""
203 from_to = ""
203 if identifier_from || identifier_to
204 if identifier_from || identifier_to
204 from_to << "#{identifier_from}.." if identifier_from
205 from_to << "#{identifier_from}.." if identifier_from
205 from_to << "#{identifier_to}" if identifier_to
206 from_to << "#{identifier_to}" if identifier_to
206 cmd_args << from_to if !from_to.empty?
207 cmd_args << from_to if !from_to.empty?
207 else
208 else
208 cmd_args += options[:includes] unless options[:includes].blank?
209 cmd_args += options[:includes] unless options[:includes].blank?
209 unless options[:excludes].blank?
210 unless options[:excludes].blank?
210 cmd_args << "--not"
211 cmd_args << "--not"
211 cmd_args += options[:excludes]
212 cmd_args += options[:excludes]
212 end
213 end
213 end
214 end
214 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
215 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
215
216
216 scm_cmd *cmd_args do |io|
217 scm_cmd *cmd_args do |io|
217 files=[]
218 files=[]
218 changeset = {}
219 changeset = {}
219 parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files
220 parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files
220
221
221 io.each_line do |line|
222 io.each_line do |line|
222 if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/
223 if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/
223 key = "commit"
224 key = "commit"
224 value = $1
225 value = $1
225 parents_str = $2
226 parents_str = $2
226 if (parsing_descr == 1 || parsing_descr == 2)
227 if (parsing_descr == 1 || parsing_descr == 2)
227 parsing_descr = 0
228 parsing_descr = 0
228 revision = Revision.new({
229 revision = Revision.new({
229 :identifier => changeset[:commit],
230 :identifier => changeset[:commit],
230 :scmid => changeset[:commit],
231 :scmid => changeset[:commit],
231 :author => changeset[:author],
232 :author => changeset[:author],
232 :time => Time.parse(changeset[:date]),
233 :time => Time.parse(changeset[:date]),
233 :message => changeset[:description],
234 :message => changeset[:description],
234 :paths => files,
235 :paths => files,
235 :parents => changeset[:parents]
236 :parents => changeset[:parents]
236 })
237 })
237 if block_given?
238 if block_given?
238 yield revision
239 yield revision
239 else
240 else
240 revs << revision
241 revs << revision
241 end
242 end
242 changeset = {}
243 changeset = {}
243 files = []
244 files = []
244 end
245 end
245 changeset[:commit] = $1
246 changeset[:commit] = $1
246 unless parents_str.nil? or parents_str == ""
247 unless parents_str.nil? or parents_str == ""
247 changeset[:parents] = parents_str.strip.split(' ')
248 changeset[:parents] = parents_str.strip.split(' ')
248 end
249 end
249 elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
250 elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
250 key = $1
251 key = $1
251 value = $2
252 value = $2
252 if key == "Author"
253 if key == "Author"
253 changeset[:author] = value
254 changeset[:author] = value
254 elsif key == "CommitDate"
255 elsif key == "CommitDate"
255 changeset[:date] = value
256 changeset[:date] = value
256 end
257 end
257 elsif (parsing_descr == 0) && line.chomp.to_s == ""
258 elsif (parsing_descr == 0) && line.chomp.to_s == ""
258 parsing_descr = 1
259 parsing_descr = 1
259 changeset[:description] = ""
260 changeset[:description] = ""
260 elsif (parsing_descr == 1 || parsing_descr == 2) \
261 elsif (parsing_descr == 1 || parsing_descr == 2) \
261 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\t(.+)$/
262 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\t(.+)$/
262 parsing_descr = 2
263 parsing_descr = 2
263 fileaction = $1
264 fileaction = $1
264 filepath = $2
265 filepath = $2
265 p = scm_iconv('UTF-8', @path_encoding, filepath)
266 p = scm_iconv('UTF-8', @path_encoding, filepath)
266 files << {:action => fileaction, :path => p}
267 files << {:action => fileaction, :path => p}
267 elsif (parsing_descr == 1 || parsing_descr == 2) \
268 elsif (parsing_descr == 1 || parsing_descr == 2) \
268 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/
269 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/
269 parsing_descr = 2
270 parsing_descr = 2
270 fileaction = $1
271 fileaction = $1
271 filepath = $3
272 filepath = $3
272 p = scm_iconv('UTF-8', @path_encoding, filepath)
273 p = scm_iconv('UTF-8', @path_encoding, filepath)
273 files << {:action => fileaction, :path => p}
274 files << {:action => fileaction, :path => p}
274 elsif (parsing_descr == 1) && line.chomp.to_s == ""
275 elsif (parsing_descr == 1) && line.chomp.to_s == ""
275 parsing_descr = 2
276 parsing_descr = 2
276 elsif (parsing_descr == 1)
277 elsif (parsing_descr == 1)
277 changeset[:description] << line[4..-1]
278 changeset[:description] << line[4..-1]
278 end
279 end
279 end
280 end
280
281
281 if changeset[:commit]
282 if changeset[:commit]
282 revision = Revision.new({
283 revision = Revision.new({
283 :identifier => changeset[:commit],
284 :identifier => changeset[:commit],
284 :scmid => changeset[:commit],
285 :scmid => changeset[:commit],
285 :author => changeset[:author],
286 :author => changeset[:author],
286 :time => Time.parse(changeset[:date]),
287 :time => Time.parse(changeset[:date]),
287 :message => changeset[:description],
288 :message => changeset[:description],
288 :paths => files,
289 :paths => files,
289 :parents => changeset[:parents]
290 :parents => changeset[:parents]
290 })
291 })
291 if block_given?
292 if block_given?
292 yield revision
293 yield revision
293 else
294 else
294 revs << revision
295 revs << revision
295 end
296 end
296 end
297 end
297 end
298 end
298 revs
299 revs
299 rescue ScmCommandAborted => e
300 rescue ScmCommandAborted => e
300 err_msg = "git log error: #{e.message}"
301 err_msg = "git log error: #{e.message}"
301 logger.error(err_msg)
302 logger.error(err_msg)
302 if block_given?
303 if block_given?
303 raise CommandFailed, err_msg
304 raise CommandFailed, err_msg
304 else
305 else
305 revs
306 revs
306 end
307 end
307 end
308 end
308
309
309 def diff(path, identifier_from, identifier_to=nil)
310 def diff(path, identifier_from, identifier_to=nil)
310 path ||= ''
311 path ||= ''
311 cmd_args = []
312 cmd_args = []
312 if identifier_to
313 if identifier_to
313 cmd_args << "diff" << "--no-color" << identifier_to << identifier_from
314 cmd_args << "diff" << "--no-color" << identifier_to << identifier_from
314 else
315 else
315 cmd_args << "show" << "--no-color" << identifier_from
316 cmd_args << "show" << "--no-color" << identifier_from
316 end
317 end
317 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty?
318 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty?
318 diff = []
319 diff = []
319 scm_cmd *cmd_args do |io|
320 scm_cmd *cmd_args do |io|
320 io.each_line do |line|
321 io.each_line do |line|
321 diff << line
322 diff << line
322 end
323 end
323 end
324 end
324 diff
325 diff
325 rescue ScmCommandAborted
326 rescue ScmCommandAborted
326 nil
327 nil
327 end
328 end
328
329
329 def annotate(path, identifier=nil)
330 def annotate(path, identifier=nil)
330 identifier = 'HEAD' if identifier.blank?
331 identifier = 'HEAD' if identifier.blank?
331 cmd_args = %w|blame|
332 cmd_args = %w|blame|
332 cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path)
333 cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path)
333 blame = Annotate.new
334 blame = Annotate.new
334 content = nil
335 content = nil
335 scm_cmd(*cmd_args) { |io| io.binmode; content = io.read }
336 scm_cmd(*cmd_args) { |io| io.binmode; content = io.read }
336 # git annotates binary files
337 # git annotates binary files
337 return nil if content.is_binary_data?
338 return nil if content.is_binary_data?
338 identifier = ''
339 identifier = ''
339 # git shows commit author on the first occurrence only
340 # git shows commit author on the first occurrence only
340 authors_by_commit = {}
341 authors_by_commit = {}
341 content.split("\n").each do |line|
342 content.split("\n").each do |line|
342 if line =~ /^([0-9a-f]{39,40})\s.*/
343 if line =~ /^([0-9a-f]{39,40})\s.*/
343 identifier = $1
344 identifier = $1
344 elsif line =~ /^author (.+)/
345 elsif line =~ /^author (.+)/
345 authors_by_commit[identifier] = $1.strip
346 authors_by_commit[identifier] = $1.strip
346 elsif line =~ /^\t(.*)/
347 elsif line =~ /^\t(.*)/
347 blame.add_line($1, Revision.new(
348 blame.add_line($1, Revision.new(
348 :identifier => identifier,
349 :identifier => identifier,
349 :revision => identifier,
350 :revision => identifier,
350 :scmid => identifier,
351 :scmid => identifier,
351 :author => authors_by_commit[identifier]
352 :author => authors_by_commit[identifier]
352 ))
353 ))
353 identifier = ''
354 identifier = ''
354 author = ''
355 author = ''
355 end
356 end
356 end
357 end
357 blame
358 blame
358 rescue ScmCommandAborted
359 rescue ScmCommandAborted
359 nil
360 nil
360 end
361 end
361
362
362 def cat(path, identifier=nil)
363 def cat(path, identifier=nil)
363 if identifier.nil?
364 if identifier.nil?
364 identifier = 'HEAD'
365 identifier = 'HEAD'
365 end
366 end
366 cmd_args = %w|show --no-color|
367 cmd_args = %w|show --no-color|
367 cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}"
368 cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}"
368 cat = nil
369 cat = nil
369 scm_cmd(*cmd_args) do |io|
370 scm_cmd(*cmd_args) do |io|
370 io.binmode
371 io.binmode
371 cat = io.read
372 cat = io.read
372 end
373 end
373 cat
374 cat
374 rescue ScmCommandAborted
375 rescue ScmCommandAborted
375 nil
376 nil
376 end
377 end
377
378
378 class Revision < Redmine::Scm::Adapters::Revision
379 class Revision < Redmine::Scm::Adapters::Revision
379 # Returns the readable identifier
380 # Returns the readable identifier
380 def format_identifier
381 def format_identifier
381 identifier[0,8]
382 identifier[0,8]
382 end
383 end
383 end
384 end
384
385
385 def scm_cmd(*args, &block)
386 def scm_cmd(*args, &block)
386 repo_path = root_url || url
387 repo_path = root_url || url
387 full_args = ['--git-dir', repo_path]
388 full_args = ['--git-dir', repo_path]
388 if self.class.client_version_above?([1, 7, 2])
389 if self.class.client_version_above?([1, 7, 2])
389 full_args << '-c' << 'core.quotepath=false'
390 full_args << '-c' << 'core.quotepath=false'
390 full_args << '-c' << 'log.decorate=no'
391 full_args << '-c' << 'log.decorate=no'
391 end
392 end
392 full_args += args
393 full_args += args
393 ret = shellout(
394 ret = shellout(
394 self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
395 self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
395 &block
396 &block
396 )
397 )
397 if $? && $?.exitstatus != 0
398 if $? && $?.exitstatus != 0
398 raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}"
399 raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}"
399 end
400 end
400 ret
401 ret
401 end
402 end
402 private :scm_cmd
403 private :scm_cmd
403 end
404 end
404 end
405 end
405 end
406 end
406 end
407 end
General Comments 0
You need to be logged in to leave comments. Login now