public
Fork of mojombo/grit
Description: Grit is a Ruby library for extracting information from a git repository in an object oriented manner.
Homepage: http://grit.rubyforge.org/
Clone URL: git://github.com/dysinger/grit.git
Search Repo:
timeout code and tests
defunkt (author)
Sun Mar 30 20:50:08 -0700 2008
commit  30e367cef2203eba2b341dc9050993b06fd1e108
tree    064fac18d116198ab6fd036f8b17aceac6d424f6
parent  5a0943123f6872e75a9b1dd0b6519dd42a186fda
...
 
 
1
2
3
 
 
 
 
 
 
 
 
 
4
5
6
7
 
8
9
10
 
 
11
12
 
13
14
15
 
 
16
17
18
19
20
21
...
26
27
28
 
 
 
29
30
31
32
33
34
 
35
36
37
38
39
40
41
42
43
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
46
 
 
 
 
 
 
47
48
49
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
18
19
20
 
21
22
23
 
24
25
26
 
27
28
29
30
31
32
33
34
...
39
40
41
42
43
44
45
46
47
48
49
 
50
51
52
53
54
55
56
 
 
 
 
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 
73
74
75
76
77
78
79
80
81
0
@@ -1,18 +1,31 @@
0
+trap("CHLD") { Process.wait(-1, Process::WNOHANG) }
0
+
0
 module Grit
0
   
0
   class Git
0
+ class GitTimeout < RuntimeError
0
+ attr_reader :command, :bytes_read
0
+
0
+ def initialize(command = nil, bytes_read = nil)
0
+ @command = command
0
+ @bytes_read = bytes_read
0
+ end
0
+ end
0
+
0
     undef_method :clone
0
     
0
     class << self
0
- attr_accessor :git_binary
0
+ attr_accessor :git_binary, :git_timeout
0
     end
0
   
0
- self.git_binary = "/usr/bin/env git"
0
+ self.git_binary = "/usr/bin/env git"
0
+ self.git_timeout = 5
0
     
0
- attr_accessor :git_dir
0
+ attr_accessor :git_dir, :bytes_read
0
     
0
     def initialize(git_dir)
0
- self.git_dir = git_dir
0
+ self.git_dir = git_dir
0
+ self.bytes_read = 0
0
     end
0
     
0
     # Run the given git command with the specified arguments and return
0
0
0
0
@@ -26,24 +39,43 @@
0
     #
0
     # Returns String
0
     def method_missing(cmd, options = {}, *args)
0
+ timeout = options.delete(:timeout)
0
+ timeout = true if timeout.nil?
0
+
0
       opt_args = transform_options(options)
0
       ext_args = args.map { |a| a == '--' ? a : "'#{a}'" }
0
       
0
       call = "#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}"
0
       puts call if Grit.debug
0
- response = sh(call)
0
+ response = timeout ? sh(call) : wild_sh(call)
0
       puts response if Grit.debug
0
       response
0
     end
0
 
0
     def sh(command)
0
       pid, _, io, _ = Open4.popen4(command)
0
- Timeout.timeout(3) { io.read }
0
- rescue Object
0
- Process.kill('KILL', pid)
0
- ''
0
+ ret = Timeout.timeout(self.class.git_timeout) { io.read }
0
+ @bytes_read += ret.size
0
+
0
+ if @bytes_read > 5242880 # 5.megabytes
0
+ bytes = @bytes_read
0
+ @bytes_read = 0
0
+ raise GitTimeout.new(command, bytes)
0
+ end
0
+
0
+ ret
0
+ rescue Object => e
0
+ Process.kill('KILL', pid) rescue nil
0
+ bytes = @bytes_read
0
+ @bytes_read = 0
0
+ raise GitTimeout.new(command, bytes)
0
     end
0
-
0
+
0
+ def wild_sh(command)
0
+ pid, _, io, _ = Open4.popen4(command)
0
+ io.read
0
+ end
0
+
0
     # Transform Ruby style options into git command line options
0
     # +options+ is a hash of Ruby style options
0
     #
...
18
19
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
0
@@ -18,5 +18,36 @@
0
     
0
     assert_equal ["-s", "-t"], @git.transform_options({:s => true, :t => true}).sort
0
   end
0
+
0
+ def test_uses_custom_sh_method
0
+ @git.expects(:sh)
0
+ @git.something
0
+ end
0
+
0
+ def test_can_skip_timeout
0
+ @git.expects(:wild_sh)
0
+ @git.something(:timeout => false)
0
+ end
0
+
0
+ def test_raises_if_too_many_bytes
0
+ @git.instance_variable_set(:@bytes_read, 6000000)
0
+ assert_raises Grit::Git::GitTimeout do
0
+ @git.something
0
+ end
0
+ end
0
+
0
+ def test_raises_on_slow_shell
0
+ Grit::Git.git_timeout = 0.5
0
+ Open4.expects(:popen4).returns([ nil, nil, mock(:read => proc { sleep 1 }), nil ])
0
+ assert_raises Grit::Git::GitTimeout do
0
+ @git.something
0
+ end
0
+ end
0
+
0
+ def test_works_fine_if_quick
0
+ output = 'output'
0
+ Open4.expects(:popen4).returns([ nil, nil, mock(:read => output), nil ])
0
+ assert_equal output, @git.something
0
+ end
0
 end

Comments

    No one has commented yet.