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