Skip to content
Newer
Older
100644 502 lines (438 sloc) 15.9 KB
4e694b9 @mojombo further file system abstractions
authored
1 require 'tempfile'
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
2 require 'posix-spawn'
d01a4cf @mojombo convert to Grit module, refactor to be more OO
authored
3 module Grit
18ec70e @mojombo massive whitespace removal
authored
4
d01a4cf @mojombo convert to Grit module, refactor to be more OO
authored
5 class Git
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
6 include POSIX::Spawn
7
30e367c @defunkt timeout code and tests
defunkt authored
8 class GitTimeout < RuntimeError
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
9 attr_accessor :command
10 attr_accessor :bytes_read
30e367c @defunkt timeout code and tests
defunkt authored
11
12 def initialize(command = nil, bytes_read = nil)
13 @command = command
14 @bytes_read = bytes_read
15 end
16 end
17
889adf5 @rtomayko Git#native can optionally raise an exception when command exits non-zero
rtomayko authored
18 # Raised when a native git command exits with non-zero.
19 class CommandFailed < StandardError
20 # The full git command that failed as a String.
21 attr_reader :command
22
23 # The integer exit status.
24 attr_reader :exitstatus
25
26 # Everything output on the command's stderr as a String.
27 attr_reader :err
28
92f1973 @rtomayko Grit::Git::CommandFailed can take a single message argument
rtomayko authored
29 def initialize(command, exitstatus=nil, err='')
30 if exitstatus
31 @command = command
32 @exitstatus = exitstatus
33 @err = err
0574dd7 @tmm1 include stderr output in Grit::Git::CommandFailed errors
tmm1 authored
34 message = "Command failed [#{exitstatus}]: #{command}"
35 message << "\n\n" << err unless err.nil? || err.empty?
36 super message
92f1973 @rtomayko Grit::Git::CommandFailed can take a single message argument
rtomayko authored
37 else
38 super command
39 end
889adf5 @rtomayko Git#native can optionally raise an exception when command exits non-zero
rtomayko authored
40 end
41 end
42
e631529 @mojombo add fork_bare
authored
43 undef_method :clone
18ec70e @mojombo massive whitespace removal
authored
44
2d22f88 @schacon added a pure-ruby alternative to diff
schacon authored
45 include GitRuby
4e694b9 @mojombo further file system abstractions
authored
46
47 def exist?
48 File.exist?(self.git_dir)
49 end
50
e976f76 @mojombo refactor more methods into git-ruby
authored
51 def put_raw_object(content, type)
52 ruby_git.put_raw_object(content, type)
53 end
54
7a39c57 @schacon updates to grit for tag api
schacon authored
55 def get_raw_object(object_id)
56 ruby_git.get_raw_object_by_sha1(object_id).content
57 end
58
f38eecb @schacon start using the GitRuby::GitObject types in the Git data api
schacon authored
59 def get_git_object(object_id)
60 ruby_git.get_raw_object_by_sha1(object_id).to_hash
61 end
62
e976f76 @mojombo refactor more methods into git-ruby
authored
63 def object_exists?(object_id)
64 ruby_git.object_exists?(object_id)
65 end
66
0bd0c5f @mojombo implement select_existing_objects
authored
67 def select_existing_objects(object_ids)
68 object_ids.select do |object_id|
69 object_exists?(object_id)
70 end
71 end
72
d01a4cf @mojombo convert to Grit module, refactor to be more OO
authored
73 class << self
f955066 @rtomayko avoid searching for git binary at load time
rtomayko authored
74 attr_accessor :git_timeout, :git_max_size
75 def git_binary
76 @git_binary ||=
77 ENV['PATH'].split(':').
78 map { |p| File.join(p, 'git') }.
79 find { |p| File.exist?(p) }
80 end
81 attr_writer :git_binary
d01a4cf @mojombo convert to Grit module, refactor to be more OO
authored
82 end
18ec70e @mojombo massive whitespace removal
authored
83
1ab3ab7 @josb Make the number of bytes to be read from git's stdout configurable.
josb authored
84 self.git_timeout = 10
85 self.git_max_size = 5242880 # 5.megabytes
18ec70e @mojombo massive whitespace removal
authored
86
4c592b4 @bobbywilson0 fix default parameter for with_timeout
bobbywilson0 authored
87 def self.with_timeout(timeout = 10)
1c002dd @schacon added some blame and merge stuff
schacon authored
88 old_timeout = Grit::Git.git_timeout
89 Grit::Git.git_timeout = timeout
90 yield
91 Grit::Git.git_timeout = old_timeout
92 end
18ec70e @mojombo massive whitespace removal
authored
93
8c4ec13 @davetron5000 sets --work-tree so that adds work
davetron5000 authored
94 attr_accessor :git_dir, :bytes_read, :work_tree
18ec70e @mojombo massive whitespace removal
authored
95
2c6af5a @mojombo implement Repo.commits
authored
96 def initialize(git_dir)
30e367c @defunkt timeout code and tests
defunkt authored
97 self.git_dir = git_dir
a88d1d9 @davetron5000 more terse and more correct
davetron5000 authored
98 self.work_tree = git_dir.gsub(/\/\.git$/,'')
30e367c @defunkt timeout code and tests
defunkt authored
99 self.bytes_read = 0
2c6af5a @mojombo implement Repo.commits
authored
100 end
18ec70e @mojombo massive whitespace removal
authored
101
ed76397 @js do some mild shell escaping when running commands
js authored
102 def shell_escape(str)
103 str.to_s.gsub("'", "\\\\'").gsub(";", '\\;')
104 end
105 alias_method :e, :shell_escape
18ec70e @mojombo massive whitespace removal
authored
106
4e694b9 @mojombo further file system abstractions
authored
107 # Check if a normal file exists on the filesystem
108 # +file+ is the relative path from the Git dir
109 #
110 # Returns Boolean
111 def fs_exist?(file)
112 File.exist?(File.join(self.git_dir, file))
113 end
18ec70e @mojombo massive whitespace removal
authored
114
afe9c14 @mojombo abstract all file system calls into git class
authored
115 # Read a normal file from the filesystem.
116 # +file+ is the relative path from the Git dir
117 #
118 # Returns the String contents of the file
119 def fs_read(file)
d7d2eb5 @rtomayko close open files as soon as possible
rtomayko authored
120 File.read(File.join(self.git_dir, file))
afe9c14 @mojombo abstract all file system calls into git class
authored
121 end
18ec70e @mojombo massive whitespace removal
authored
122
afe9c14 @mojombo abstract all file system calls into git class
authored
123 # Write a normal file to the filesystem.
124 # +file+ is the relative path from the Git dir
125 # +contents+ is the String content to be written
126 #
127 # Returns nothing
128 def fs_write(file, contents)
129 path = File.join(self.git_dir, file)
130 FileUtils.mkdir_p(File.dirname(path))
131 File.open(path, 'w') do |f|
132 f.write(contents)
133 end
134 end
18ec70e @mojombo massive whitespace removal
authored
135
afe9c14 @mojombo abstract all file system calls into git class
authored
136 # Delete a normal file from the filesystem
137 # +file+ is the relative path from the Git dir
138 #
139 # Returns nothing
140 def fs_delete(file)
4e694b9 @mojombo further file system abstractions
authored
141 FileUtils.rm_rf(File.join(self.git_dir, file))
142 end
18ec70e @mojombo massive whitespace removal
authored
143
4e694b9 @mojombo further file system abstractions
authored
144 # Move a normal file
145 # +from+ is the relative path to the current file
146 # +to+ is the relative path to the destination file
147 #
148 # Returns nothing
149 def fs_move(from, to)
150 FileUtils.mv(File.join(self.git_dir, from), File.join(self.git_dir, to))
151 end
18ec70e @mojombo massive whitespace removal
authored
152
4e694b9 @mojombo further file system abstractions
authored
153 # Make a directory
154 # +dir+ is the relative path to the directory to create
155 #
156 # Returns nothing
157 def fs_mkdir(dir)
158 FileUtils.mkdir_p(File.join(self.git_dir, dir))
159 end
18ec70e @mojombo massive whitespace removal
authored
160
4e694b9 @mojombo further file system abstractions
authored
161 # Chmod the the file or dir and everything beneath
162 # +file+ is the relative path from the Git dir
163 #
164 # Returns nothing
165 def fs_chmod(mode, file = '/')
166 FileUtils.chmod_R(mode, File.join(self.git_dir, file))
167 end
168
169 def list_remotes
170 remotes = []
171 Dir.chdir(File.join(self.git_dir, 'refs/remotes')) do
172 remotes = Dir.glob('*')
173 end
174 remotes
175 rescue
176 []
177 end
18ec70e @mojombo massive whitespace removal
authored
178
4e694b9 @mojombo further file system abstractions
authored
179 def create_tempfile(seed, unlink = false)
180 path = Tempfile.new(seed).path
181 File.unlink(path) if unlink
182 return path
183 end
18ec70e @mojombo massive whitespace removal
authored
184
4fe0ec0 @mojombo fix tags
authored
185 def commit_from_sha(id)
186 git_ruby_repo = GitRuby::Repository.new(self.git_dir)
187 object = git_ruby_repo.get_object_by_sha1(id)
188
189 if object.type == :commit
190 id
191 elsif object.type == :tag
192 object.object
193 else
194 ''
195 end
196 end
18ec70e @mojombo massive whitespace removal
authored
197
18bfda9 @technoweenie add docs to the patch methods
technoweenie authored
198 # Checks if the patch of a commit can be applied to the given head.
199 #
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
200 # options - grit command options hash
18bfda9 @technoweenie add docs to the patch methods
technoweenie authored
201 # head_sha - String SHA or ref to check the patch against.
202 # applies_sha - String SHA of the patch. The patch itself is retrieved
203 # with #get_patch.
204 #
205 # Returns 0 if the patch applies cleanly (according to `git apply`), or
206 # an Integer that is the sum of the failed exit statuses.
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
207 def check_applies(options={}, head_sha=nil, applies_sha=nil)
208 options, head_sha, applies_sha = {}, options, head_sha if !options.is_a?(Hash)
209 options = options.dup
210 options[:env] &&= options[:env].dup
211
4e694b9 @mojombo further file system abstractions
authored
212 git_index = create_tempfile('index', true)
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
213 (options[:env] ||= {}).merge!('GIT_INDEX_FILE' => git_index)
214 options[:raise] = true
215
216 status = 0
6684afe @technoweenie replace the old #raw_git stuff with #native calls for the git patchin…
technoweenie authored
217 begin
218 native(:read_tree, options.dup, head_sha)
219 stdin = native(:diff, options.dup, "#{applies_sha}^", applies_sha)
220 native(:apply, options.merge(:check => true, :cached => true, :input => stdin))
3392866 @technoweenie when #check_applies fails, add the exitstatus to the accumulated stat…
technoweenie authored
221 rescue CommandFailed => fail
222 status += fail.exitstatus
6684afe @technoweenie replace the old #raw_git stuff with #native calls for the git patchin…
technoweenie authored
223 end
224 status
4e694b9 @mojombo further file system abstractions
authored
225 end
18ec70e @mojombo massive whitespace removal
authored
226
18bfda9 @technoweenie add docs to the patch methods
technoweenie authored
227 # Gets a patch for a given SHA using `git diff`.
228 #
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
229 # options - grit command options hash
18bfda9 @technoweenie add docs to the patch methods
technoweenie authored
230 # applies_sha - String SHA to get the patch from, using this command:
231 # `git diff #{applies_sha}^ #{applies_sha}`
232 #
233 # Returns the String patch from `git diff`.
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
234 def get_patch(options={}, applies_sha=nil)
235 options, applies_sha = {}, options if !options.is_a?(Hash)
236 options = options.dup
237 options[:env] &&= options[:env].dup
238
4e694b9 @mojombo further file system abstractions
authored
239 git_index = create_tempfile('index', true)
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
240 (options[:env] ||= {}).merge!('GIT_INDEX_FILE' => git_index)
241
242 native(:diff, options, "#{applies_sha}^", applies_sha)
afe9c14 @mojombo abstract all file system calls into git class
authored
243 end
18ec70e @mojombo massive whitespace removal
authored
244
18bfda9 @technoweenie add docs to the patch methods
technoweenie authored
245 # Applies the given patch against the given SHA of the current repo.
246 #
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
247 # options - grit command hash
18bfda9 @technoweenie add docs to the patch methods
technoweenie authored
248 # head_sha - String SHA or ref to apply the patch to.
249 # patch - The String patch to apply. Get this from #get_patch.
250 #
251 # Returns the String Tree SHA on a successful patch application, or false.
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
252 def apply_patch(options={}, head_sha=nil, patch=nil)
253 options, head_sha, patch = {}, options, head_sha if !options.is_a?(Hash)
254 options = options.dup
255 options[:env] &&= options[:env].dup
256 options[:raise] = true
257
4e694b9 @mojombo further file system abstractions
authored
258 git_index = create_tempfile('index', true)
e116026 @rtomayko Grit::Git check_applies / patch related methods take command hash
rtomayko authored
259 (options[:env] ||= {}).merge!('GIT_INDEX_FILE' => git_index)
18ec70e @mojombo massive whitespace removal
authored
260
6684afe @technoweenie replace the old #raw_git stuff with #native calls for the git patchin…
technoweenie authored
261 begin
262 native(:read_tree, options.dup, head_sha)
263 native(:apply, options.merge(:cached => true, :input => patch))
264 rescue CommandFailed
265 return false
4e694b9 @mojombo further file system abstractions
authored
266 end
6684afe @technoweenie replace the old #raw_git stuff with #native calls for the git patchin…
technoweenie authored
267 native(:write_tree, :env => options[:env]).to_s.chomp!
4e694b9 @mojombo further file system abstractions
authored
268 end
269
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
270 # Execute a git command, bypassing any library implementation.
271 #
272 # cmd - The name of the git command as a Symbol. Underscores are
273 # converted to dashes as in :rev_parse => 'rev-parse'.
274 # options - Command line option arguments passed to the git command.
275 # Single char keys are converted to short options (:a => -a).
276 # Multi-char keys are converted to long options (:arg => '--arg').
277 # Underscores in keys are converted to dashes. These special options
278 # are used to control command execution and are not passed in command
279 # invocation:
280 # :timeout - Maximum amount of time the command can run for before
281 # being aborted. When true, use Grit::Git.git_timeout; when numeric,
282 # use that number of seconds; when false or 0, disable timeout.
283 # :base - Set false to avoid passing the --git-dir argument when
284 # invoking the git command.
96f604c @rtomayko Git#native takes environment for git child process
rtomayko authored
285 # :env - Hash of environment variable key/values that are set on the
286 # child process.
889adf5 @rtomayko Git#native can optionally raise an exception when command exits non-zero
rtomayko authored
287 # :raise - When set true, commands that exit with a non-zero status
3f4efb2 @rtomayko emulate native :env option when fork not available
rtomayko authored
288 # raise a CommandFailed exception. This option is available only on
289 # platforms that support fork(2).
019bae7 @rtomayko Grit::Git#native can return [0, out, err] tuple instead of just stdout
rtomayko authored
290 # :process_info - By default, a single string with output written to
291 # the process's stdout is returned. Setting this option to true
292 # results in a [exitstatus, out, err] tuple being returned instead.
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
293 # args - Non-option arguments passed on the command line.
294 #
295 # Optionally yields to the block an IO object attached to the child
296 # process's STDIN.
d01a4cf @mojombo convert to Grit module, refactor to be more OO
authored
297 #
298 # Examples
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
299 # git.native(:rev_list, {:max_count => 10, :header => true}, "master")
300 #
019bae7 @rtomayko Grit::Git#native can return [0, out, err] tuple instead of just stdout
rtomayko authored
301 # Returns a String with all output written to the child process's stdout
302 # when the :process_info option is not set.
303 # Returns a [exitstatus, out, err] tuple when the :process_info option is
304 # set. The exitstatus is an small integer that was the process's exit
305 # status. The out and err elements are the data written to stdout and
306 # stderr as Strings.
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
307 # Raises Grit::Git::GitTimeout when the timeout is exceeded or when more
308 # than Grit::Git.git_max_size bytes are output.
889adf5 @rtomayko Git#native can optionally raise an exception when command exits non-zero
rtomayko authored
309 # Raises Grit::Git::CommandFailed when the :raise option is set true and the
310 # git command exits with a non-zero exit status. The CommandFailed's #command,
311 # #exitstatus, and #err attributes can be used to retrieve additional
312 # detail about the error.
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
313 def native(cmd, options = {}, *args, &block)
314 args = args.first if args.size == 1 && args[0].is_a?(Array)
ef2870b @dkowis Fix for files with spaces, including tests
dkowis authored
315 args.map! { |a| a.to_s }
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
316 args.reject! { |a| a.empty? }
317
3f4efb2 @rtomayko emulate native :env option when fork not available
rtomayko authored
318 # special option arguments
319 env = options.delete(:env) || {}
320 raise_errors = options.delete(:raise)
019bae7 @rtomayko Grit::Git#native can return [0, out, err] tuple instead of just stdout
rtomayko authored
321 process_info = options.delete(:process_info)
3f4efb2 @rtomayko emulate native :env option when fork not available
rtomayko authored
322
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
323 # fall back to using a shell when the last argument looks like it wants to
324 # start a pipeline for compatibility with previous versions of grit.
325 return run(prefix, cmd, '', options, args) if args[-1].to_s[0] == ?|
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
326
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
327 # more options
2fb7d5d @rtomayko handle git process input that exceeds max pipe buffer
rtomayko authored
328 input = options.delete(:input)
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
329 timeout = options.delete(:timeout); timeout = true if timeout.nil?
330 base = options.delete(:base); base = true if base.nil?
331 chdir = options.delete(:chdir)
2fb7d5d @rtomayko handle git process input that exceeds max pipe buffer
rtomayko authored
332
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
333 # build up the git process argv
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
334 argv = []
335 argv << Git.git_binary
336 argv << "--git-dir=#{git_dir}" if base
337 argv << cmd.to_s.tr('_', '-')
338 argv.concat(options_to_argv(options))
339 argv.concat(args)
340
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
341 # run it and deal with fallout
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
342 Grit.log(argv.join(' ')) if Grit.debug
95efc13 @rtomayko get command timeout support working again
rtomayko authored
343
344 process =
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
345 Child.new(env, *(argv + [{
95efc13 @rtomayko get command timeout support working again
rtomayko authored
346 :input => input,
347 :chdir => chdir,
7dd3d35 @rtomayko get git_max_size support working again
rtomayko authored
348 :timeout => (Grit::Git.git_timeout if timeout == true),
349 :max => (Grit::Git.git_max_size if timeout == true)
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
350 }]))
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
351 Grit.log(process.out) if Grit.debug
352 Grit.log(process.err) if Grit.debug
019bae7 @rtomayko Grit::Git#native can return [0, out, err] tuple instead of just stdout
rtomayko authored
353
354 status = process.status
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
355 if raise_errors && !status.success?
356 raise CommandFailed.new(argv.join(' '), status.exitstatus, process.err)
019bae7 @rtomayko Grit::Git#native can return [0, out, err] tuple instead of just stdout
rtomayko authored
357 elsif process_info
358 [status.exitstatus, process.out, process.err]
889adf5 @rtomayko Git#native can optionally raise an exception when command exits non-zero
rtomayko authored
359 else
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
360 process.out
889adf5 @rtomayko Git#native can optionally raise an exception when command exits non-zero
rtomayko authored
361 end
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
362 rescue TimeoutExceeded, MaximumOutputExceeded
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
363 raise GitTimeout, argv.join(' ')
364 end
365
366 # Methods not defined by a library implementation execute the git command
367 # using #native, passing the method name as the git command name.
368 #
369 # Examples:
917522c @mojombo more code comments throughout
authored
370 # git.rev_list({:max_count => 10, :header => true}, "master")
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
371 def method_missing(cmd, options={}, *args, &block)
372 native(cmd, options, *args, &block)
373 end
374
375 # Transform a ruby-style options hash to command-line arguments sutiable for
376 # use with Kernel::exec. No shell escaping is performed.
d01a4cf @mojombo convert to Grit module, refactor to be more OO
authored
377 #
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
378 # Returns an Array of String option arguments.
379 def options_to_argv(options)
380 argv = []
381 options.each do |key, val|
382 if key.to_s.size == 1
383 if val == true
384 argv << "-#{key}"
385 elsif val == false
386 # ignore
387 else
388 argv << "-#{key}"
389 argv << val.to_s
390 end
391 else
392 if val == true
393 argv << "--#{key.to_s.tr('_', '-')}"
394 elsif val == false
395 # ignore
396 else
397 argv << "--#{key.to_s.tr('_', '-')}=#{val}"
398 end
399 end
400 end
401 argv
823a9d9 cleared out errors by adding in Grit::Git#run method
Bryce Kerley authored
402 end
403
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
404 # Simple wrapper around Timeout::timeout.
e976f76 @mojombo refactor more methods into git-ruby
authored
405 #
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
406 # seconds - Float number of seconds before a Timeout::Error is raised. When
407 # true, the Grit::Git.git_timeout value is used. When the timeout is less
408 # than or equal to 0, no timeout is established.
409 #
410 # Raises Timeout::Error when the timeout has elapsed.
411 def timeout_after(seconds)
412 seconds = self.class.git_timeout if seconds == true
413 if seconds && seconds > 0
414 Timeout.timeout(seconds) { yield }
415 else
416 yield
417 end
e976f76 @mojombo refactor more methods into git-ruby
authored
418 end
419
1cfcc1b @rtomayko avoid /bin/sh + escaping; exec git commands directly
rtomayko authored
420 # DEPRECATED OPEN3-BASED COMMAND EXECUTION
421
28ed493 @technoweenie add Grit::Repo#batch for getting multiple commits in a single native …
technoweenie authored
422 def run(prefix, cmd, postfix, options, args, &block)
1c002dd @schacon added some blame and merge stuff
schacon authored
423 timeout = options.delete(:timeout) rescue nil
30e367c @defunkt timeout code and tests
defunkt authored
424 timeout = true if timeout.nil?
425
8869608 @mojombo Add Repo#init.
authored
426 base = options.delete(:base) rescue nil
427 base = true if base.nil?
428
c8306fe @rtomayko open3 based Git#run method also supports :input option
rtomayko authored
429 if input = options.delete(:input)
430 block = lambda { |stdin| stdin.write(input) }
431 end
432
3b19302 @mojombo big refactor to do lazy loading
authored
433 opt_args = transform_options(options)
18ec70e @mojombo massive whitespace removal
authored
434
d5cde35 @mojombo windows support
authored
435 if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
3073a5c @schacon merge in tag listing fix
schacon authored
436 ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|' || Grit.no_quote) ? a : "\"#{e(a)}\"" }
8869608 @mojombo Add Repo#init.
authored
437 gitdir = base ? "--git-dir=\"#{self.git_dir}\"" : ""
438 call = "#{prefix}#{Git.git_binary} #{gitdir} #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{e(postfix)}"
d5cde35 @mojombo windows support
authored
439 else
3073a5c @schacon merge in tag listing fix
schacon authored
440 ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|' || Grit.no_quote) ? a : "'#{e(a)}'" }
8869608 @mojombo Add Repo#init.
authored
441 gitdir = base ? "--git-dir='#{self.git_dir}'" : ""
442 call = "#{prefix}#{Git.git_binary} #{gitdir} #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{e(postfix)}"
d5cde35 @mojombo windows support
authored
443 end
95efc13 @rtomayko get command timeout support working again
rtomayko authored
444
3dabb6a @rsanheim allow sending debug messages to a user defined logger if provided; te…
rsanheim authored
445 Grit.log(call) if Grit.debug
28ed493 @technoweenie add Grit::Repo#batch for getting multiple commits in a single native …
technoweenie authored
446 response, err = timeout ? sh(call, &block) : wild_sh(call, &block)
3dabb6a @rsanheim allow sending debug messages to a user defined logger if provided; te…
rsanheim authored
447 Grit.log(response) if Grit.debug
06bae5a @rsanheim capture stderr and log it if debug is true when running commands
rsanheim authored
448 Grit.log(err) if Grit.debug
b6e1b76 @mojombo implement Repo.init_bare
authored
449 response
3b19302 @mojombo big refactor to do lazy loading
authored
450 end
5a09431 @defunkt add timeout protection to grit
defunkt authored
451
28ed493 @technoweenie add Grit::Repo#batch for getting multiple commits in a single native …
technoweenie authored
452 def sh(command, &block)
7dd3d35 @rtomayko get git_max_size support working again
rtomayko authored
453 process =
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
454 Child.new(
455 command,
7dd3d35 @rtomayko get git_max_size support working again
rtomayko authored
456 :timeout => Git.git_timeout,
457 :max => Git.git_max_size
458 )
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
459 [process.out, process.err]
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
460 rescue TimeoutExceeded, MaximumOutputExceeded
95efc13 @rtomayko get command timeout support working again
rtomayko authored
461 raise GitTimeout, command
30e367c @defunkt timeout code and tests
defunkt authored
462 end
463
28ed493 @technoweenie add Grit::Repo#batch for getting multiple commits in a single native …
technoweenie authored
464 def wild_sh(command, &block)
12c9874 @tmm1 remove Grit::Process in favor of POSIX::Spawn::Child
tmm1 authored
465 process = Child.new(command)
6a9b7f4 @rtomayko Grit::Git uses Grit::Process for all native command invocations
rtomayko authored
466 [process.out, process.err]
5a09431 @defunkt add timeout protection to grit
defunkt authored
467 end
30e367c @defunkt timeout code and tests
defunkt authored
468
917522c @mojombo more code comments throughout
authored
469 # Transform Ruby style options into git command line options
470 # +options+ is a hash of Ruby style options
471 #
472 # Returns String[]
473 # e.g. ["--max-count=10", "--header"]
3b19302 @mojombo big refactor to do lazy loading
authored
474 def transform_options(options)
475 args = []
476 options.keys.each do |opt|
8c7f4e1 @mojombo dynamically rewrite ruby style git options
authored
477 if opt.to_s.size == 1
478 if options[opt] == true
479 args << "-#{opt}"
82cac1a @mojombo allow setting of options to false to override true defaults
authored
480 elsif options[opt] == false
481 # ignore
8c7f4e1 @mojombo dynamically rewrite ruby style git options
authored
482 else
483 val = options.delete(opt)
ed76397 @js do some mild shell escaping when running commands
js authored
484 args << "-#{opt.to_s} '#{e(val)}'"
8c7f4e1 @mojombo dynamically rewrite ruby style git options
authored
485 end
486 else
3b19302 @mojombo big refactor to do lazy loading
authored
487 if options[opt] == true
8c7f4e1 @mojombo dynamically rewrite ruby style git options
authored
488 args << "--#{opt.to_s.gsub(/_/, '-')}"
82cac1a @mojombo allow setting of options to false to override true defaults
authored
489 elsif options[opt] == false
490 # ignore
3b19302 @mojombo big refactor to do lazy loading
authored
491 else
492 val = options.delete(opt)
ed76397 @js do some mild shell escaping when running commands
js authored
493 args << "--#{opt.to_s.gsub(/_/, '-')}='#{e(val)}'"
3b19302 @mojombo big refactor to do lazy loading
authored
494 end
495 end
496 end
497 args
d01a4cf @mojombo convert to Grit module, refactor to be more OO
authored
498 end
499 end # Git
18ec70e @mojombo massive whitespace removal
authored
500
5a09431 @defunkt add timeout protection to grit
defunkt authored
501 end # Grit
Something went wrong with that request. Please try again.