sentry_breakpad 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96f21c80f9bc540808c52392ac3351b836327867
4
- data.tar.gz: 01a4ace182a68378bcaddeb6971aef2ad2c4be62
3
+ metadata.gz: 57728a993a05e1ce50d874845c1a60eb5b6cb9d0
4
+ data.tar.gz: e9d3d50f2cb26f67fa8f693e1f5c02f065ce7824
5
5
  SHA512:
6
- metadata.gz: 446a53d3308df54fc9b529e528e1aa24f56a28e8a78c8a4ef421f6df9993442144571f89dc3ca92c80b9fe5379ddad13b73c33b513948e549c92a82fdec6d5e1
7
- data.tar.gz: 683d0cf639f1981fed76da382771faa932803e9c9595a38d34a96d5df79f657a7c003262ed83659aeb945bb513c6e63c9412227bc1c6631735a8a659ae8fad13
6
+ metadata.gz: 794f61ff285ffa3f2645a815afa1d00357abd6fb656076e143b39a22f8a6443f24d0e0fa1fd664e5b8e6470126fa3e2a4357bed0952977c68e397e13349475f6
7
+ data.tar.gz: f64c38d31914d28a01cda09cf32b8c1b90ab8302572393b2d5ba5956fa7d64fa0b54386d8fe52a099fffd6febea46a989a409d53af014824afa56f75a8bf667d
data/.gitignore CHANGED
@@ -1,6 +1,5 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
- /Gemfile.lock
4
3
  /_yardoc/
5
4
  /coverage/
6
5
  /doc/
@@ -0,0 +1,14 @@
1
+ AllCops:
2
+ DisplayCopNames: true
3
+
4
+ Metrics/LineLength:
5
+ Max: 100
6
+
7
+ Metrics/MethodLength:
8
+ Max: 15
9
+
10
+ Documentation:
11
+ Enabled: false
12
+
13
+ Style/AccessModifierIndentation:
14
+ EnforcedStyle: outdent
@@ -1,4 +1,14 @@
1
1
  language: ruby
2
+ cache: bundler
2
3
  rvm:
3
- - 2.2.2
4
- before_install: gem install bundler -v 1.10.6
4
+ - 1.9
5
+ - 1.9.3
6
+ - 2.0
7
+ - 2.1
8
+ - 2.2
9
+ - 2.3.3
10
+ - 2.4.0
11
+ before_install: gem update --remote bundler
12
+ script:
13
+ - bundle exec rspec
14
+ - bundle exec rubocop -c .rubocop.yml
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sentry_breakpad (0.1.10)
5
+ sentry-raven (~> 2.2.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ast (2.3.0)
11
+ diff-lcs (1.2.5)
12
+ faraday (0.10.0)
13
+ multipart-post (>= 1.2, < 3)
14
+ multipart-post (2.0.0)
15
+ parser (2.3.3.1)
16
+ ast (~> 2.2)
17
+ powerpack (0.1.1)
18
+ rainbow (2.1.0)
19
+ rspec (3.4.0)
20
+ rspec-core (~> 3.4.0)
21
+ rspec-expectations (~> 3.4.0)
22
+ rspec-mocks (~> 3.4.0)
23
+ rspec-core (3.4.2)
24
+ rspec-support (~> 3.4.0)
25
+ rspec-expectations (3.4.0)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.4.0)
28
+ rspec-mocks (3.4.1)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.4.0)
31
+ rspec-support (3.4.1)
32
+ rubocop (0.38.0)
33
+ parser (>= 2.3.0.6, < 3.0)
34
+ powerpack (~> 0.1)
35
+ rainbow (>= 1.99.1, < 3.0)
36
+ ruby-progressbar (~> 1.7)
37
+ unicode-display_width (~> 1.0, >= 1.0.1)
38
+ ruby-progressbar (1.8.1)
39
+ sentry-raven (2.2.0)
40
+ faraday (>= 0.7.6, < 1.0)
41
+ unicode-display_width (1.1.1)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ rspec
48
+ rubocop
49
+ sentry_breakpad!
50
+
51
+ BUNDLED WITH
52
+ 1.13.6
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://api.travis-ci.org/wk8/sentry_breakpad.svg?branch=master)](https://travis-ci.org/wk8/sentry_breakpad)
2
+
1
3
  # SentryBreakpad
2
4
 
3
5
  So you've integrated [Google
@@ -139,7 +141,6 @@ SentryBreakpad.send_from_file('/path/to/report', {
139
141
  ```
140
142
 
141
143
  The exhaustive list of all the extra information that can be passed can be found
142
- at https://github.com/getsentry/raven-ruby/blob/0.15.3/lib/raven/event.rb#L31-L49.
143
144
 
144
145
  Please note that all of the above assumes that `Raven` has been properly configured
145
146
  (we use `Raven.client` to send the generated events)
@@ -154,7 +155,6 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
154
155
 
155
156
  Bug reports and pull requests are welcome on GitHub at https://github.com/wk8/sentry_breakpad.
156
157
 
157
-
158
158
  ## License
159
159
 
160
160
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "sentry_breakpad"
3
+ require 'bundler/setup'
4
+ require 'sentry_breakpad'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
10
+ # require 'pry'
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start
@@ -1,22 +1,23 @@
1
1
  require 'sentry_breakpad/version'
2
2
  require 'sentry_breakpad/breakpad_parser'
3
+ require 'sentry_breakpad/hash_helper'
3
4
 
4
5
  require 'raven'
5
6
 
6
7
  module SentryBreakpad
7
8
  class << self
8
- def send_from_file(file_path, extra_info = {}, include_whole_report = true)
9
- send_event(BreakpadParser.from_file(file_path), extra_info, include_whole_report)
9
+ def send_from_file(file_path, extra_info = {})
10
+ send_event(BreakpadParser.from_file(file_path), extra_info)
10
11
  end
11
12
 
12
- def send_from_string(string, extra_info = {}, include_whole_report = true)
13
- send_event(BreakpadParser.new(string), extra_info, include_whole_report)
13
+ def send_from_string(string, extra_info = {})
14
+ send_event(BreakpadParser.new(string), extra_info)
14
15
  end
15
16
 
16
17
  private
17
18
 
18
- def send_event(parser, extra_info, include_whole_report)
19
- Raven.client.send_event(parser.raven_event(extra_info, include_whole_report))
19
+ def send_event(parser, extra_info)
20
+ Raven.client.send_event(parser.raven_event(extra_info))
20
21
  end
21
22
  end
22
23
  end
@@ -1,63 +1,59 @@
1
1
  require 'raven'
2
2
 
3
3
  module SentryBreakpad
4
- # parses a breakpad report
5
- class BreakpadParser
4
+ # parses a breakpad report and turns it into a Raven event
5
+ class BreakpadParser # rubocop:disable Metrics/ClassLength
6
6
  def self.from_file(file_path)
7
- new(File.open(file_path).read)
7
+ new(File.read(file_path))
8
8
  end
9
9
 
10
10
  def initialize(breakpad_report_content)
11
11
  @breakpad_report_content = breakpad_report_content
12
- @parsed = false
13
12
 
14
13
  @message = nil
15
14
  @tags = {}
16
15
  @crashed_thread_stacktrace = []
16
+ # TODO: this is not leveraged yet, because the ruby-raven gem doesn't
17
+ # support this yet...
18
+ # come back to integrating other threads' stacktraces when
19
+ # https://github.com/getsentry/raven-ruby/issues/551
20
+ # is resolved
21
+ @other_threads_stacktraces = {}
17
22
  @culprit = nil
18
23
  @modules = {}
19
24
  @extra = {}
20
- end
21
25
 
22
- def raven_event(extra_info = {}, include_whole_report = true)
23
- hash = deep_merge(raven_event_hash(include_whole_report), extra_info)
24
- Raven::Event.new(hash)
26
+ parse!
25
27
  end
26
28
 
27
- def raven_event_hash(include_whole_report = true)
28
- parse
29
-
30
- extra = if include_whole_report
31
- @extra.merge({'raw_breakpad_report' => @breakpad_report_content})
32
- else
33
- @extra
29
+ def raven_event(extra_info = {})
30
+ hash = HashHelper.deep_merge!(base_event_hash, HashHelper.deep_symbolize_keys!(extra_info))
31
+ Raven::Event.new(hash).tap do |event|
32
+ unless @crashed_thread_stacktrace.empty?
33
+ event[:stacktrace] = { frames: @crashed_thread_stacktrace }
34
+ end
34
35
  end
35
-
36
- {
37
- 'message' => @message,
38
- 'tags' => @tags,
39
- 'culprit' => @culprit,
40
- 'modules' => @modules,
41
- 'extra' => extra,
42
- 'level' => 'fatal',
43
- 'logger' => 'breakpad',
44
- 'interfaces' => {
45
- 'stacktrace' => {
46
- 'frames' => @crashed_thread_stacktrace
47
- }
48
- }
49
- }
50
36
  end
51
37
 
52
38
  private
53
39
 
54
- def parse
55
- return if @parsed
40
+ def base_event_hash
41
+ {
42
+ message: @message,
43
+ tags: @tags,
44
+ culprit: @culprit,
45
+ modules: @modules,
46
+ extra: @extra,
47
+ level: 'fatal',
48
+ logger: 'breakpad'
49
+ }
50
+ end
56
51
 
52
+ def parse!
57
53
  parse_lines(@breakpad_report_content.split("\n").reverse!)
58
54
  end
59
55
 
60
- def parse_lines(lines)
56
+ def parse_lines(lines) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength, Metrics/LineLength
61
57
  until lines.empty?
62
58
  case lines.last
63
59
  when /^Operating system:/
@@ -68,8 +64,8 @@ module SentryBreakpad
68
64
  parse_crash_reason(lines.pop)
69
65
  when /^Crash address:/
70
66
  parse_crash_address(lines.pop)
71
- when /^Thread ([0-9]+) \(crashed\)/
72
- parse_crashed_thread_stacktrace(lines, $1.to_i)
67
+ when /^Thread ([0-9]+)(\s+\(crashed\))?/
68
+ parse_thread_stacktrace(lines, Regexp.last_match[1].to_i, !Regexp.last_match[2].nil?)
73
69
  when /^Loaded modules:/
74
70
  parse_loaded_modules(lines)
75
71
  else
@@ -82,7 +78,15 @@ module SentryBreakpad
82
78
  # Operating system: Windows NT
83
79
  # 6.1.7601 Service Pack 1
84
80
  def parse_operating_system(lines)
85
- parse_indented_section(lines, 'Operating system:', 'os')
81
+ parse_indented_section(lines, 'Operating system:', :os)
82
+
83
+ if @tags[:os]
84
+ @extra[:server] ||= {}
85
+ @extra[:server][:os] = {
86
+ name: @tags[:os],
87
+ version: @tags[:os_full]
88
+ }
89
+ end
86
90
  end
87
91
 
88
92
  # Parses something of the form
@@ -90,7 +94,7 @@ module SentryBreakpad
90
94
  # GenuineIntel family 6 model 70 stepping 1
91
95
  # 4 CPUs
92
96
  def parse_cpu(lines)
93
- parse_indented_section(lines, 'CPU:', 'cpu')
97
+ parse_indented_section(lines, 'CPU:', :cpu)
94
98
  end
95
99
 
96
100
  def parse_indented_section(lines, prefix, tag_name)
@@ -102,7 +106,7 @@ module SentryBreakpad
102
106
  end
103
107
 
104
108
  @tags[tag_name] = short
105
- @tags["#{tag_name}_full"] = long
109
+ @tags["#{tag_name}_full".to_sym] = long
106
110
  end
107
111
 
108
112
  # Parses a single line like
@@ -110,12 +114,12 @@ module SentryBreakpad
110
114
  def parse_crash_reason(line)
111
115
  reason = remove_prefix(line, 'Crash reason:')
112
116
 
113
- if @message.nil?
114
- @message = reason
115
- else
116
- # we parse the crashed thread first
117
- @message = "#{reason} at #{@message}"
118
- end
117
+ @message = if @message.nil?
118
+ reason
119
+ else
120
+ # we parse the crashed thread first
121
+ "#{reason} at #{@message}"
122
+ end
119
123
  end
120
124
 
121
125
  # Parses a single line like
@@ -123,7 +127,7 @@ module SentryBreakpad
123
127
  def parse_crash_address(line)
124
128
  address = remove_prefix(line, 'Crash address:')
125
129
 
126
- @extra['crash_address'] = address
130
+ @extra[:crash_address] = address
127
131
  end
128
132
 
129
133
  def remove_prefix(line, prefix)
@@ -131,8 +135,9 @@ module SentryBreakpad
131
135
  line.strip
132
136
  end
133
137
 
134
- BACKTRACE_LINE_REGEX = /^\s*([0-9]+)\s+(.*)\s+(?:\[(([^ ]+)\s+:\s+([0-9]+))\s+\+\s+0x[0-9a-f]+\]|\+\s+0x[0-9a-f]+)\s*$/
138
+ BACKTRACE_LINE_REGEX = /^\s*([0-9]+)\s+(.*)\s+(?:\[(([^ ]+)\s+:\s+([0-9]+))\s+\+\s+0x[0-9a-f]+\]|\+\s+0x[0-9a-f]+)\s*$/ # rubocop:disable Metrics/LineLength
135
139
 
140
+ # rubocop:disable Metrics/LineLength
136
141
  # Parses something of the form
137
142
  # Thread 0 (crashed)
138
143
  # 0 ETClient.exe!QString::~QString() [qstring.h : 992 + 0xa]
@@ -182,48 +187,58 @@ module SentryBreakpad
182
187
  # 14 ETClient.exe!WinMain + 0x21358
183
188
  # eip = 0x015bb068 esp = 0x0018d690 ebp = 0x0018d7f8
184
189
  # Found by: call frame info
185
- def parse_crashed_thread_stacktrace(lines, thread_id)
190
+ # rubocop:enable Metrics/LineLength
191
+ def parse_thread_stacktrace(lines, thread_id, is_crashed_thread)
186
192
  # remove the 1st line
187
193
  lines.pop
188
194
 
189
195
  stacktrace = []
190
196
  process_matching_lines(lines, BACKTRACE_LINE_REGEX) do |match|
191
- frame_nb = match[1]
192
- function = match[2]
193
- filename = match[4] || 'unknown'
194
- lineno = match[5]
195
-
196
- frame = {
197
- 'filename' => filename,
198
- 'function' => function
199
- }
200
- frame['lineno'] = lineno.to_i if lineno
197
+ stacktrace << parse_crashed_thread_stacktrace_line(match, is_crashed_thread)
198
+ end
201
199
 
202
- stacktrace << frame
200
+ # sentry wants their stacktrace with the oldest frame first
201
+ stacktrace = stacktrace.reverse
203
202
 
204
- if frame_nb.to_i == 0
205
- @culprit = function
203
+ if is_crashed_thread
204
+ @crashed_thread_stacktrace = stacktrace
205
+ @extra[:crashed_thread_id] = thread_id
206
+ else
207
+ @other_threads_stacktraces[thread_id] = stacktrace
208
+ end
209
+ end
206
210
 
207
- message_tail = function
208
- message_tail += " (#{match[3]})" if match[3]
211
+ def parse_crashed_thread_stacktrace_line(match, is_crashed_thread)
212
+ frame_nb = match[1]
213
+ function = match[2]
214
+ filename = match[4] || 'unknown'
215
+ lineno = match[5]
209
216
 
210
- if @message.nil?
211
- @message = message_tail
212
- else
213
- # already parsed the crash reason
214
- @message += " at #{message_tail}"
215
- end
216
- end
217
- end
217
+ parse_culprit_and_message(function, match[3]) if is_crashed_thread && frame_nb.to_i == 0
218
218
 
219
- # sentry wants their stacktrace with the oldest frame first
220
- @crashed_thread_stacktrace = stacktrace.reverse
219
+ {
220
+ filename: filename,
221
+ function: function
222
+ }.tap { |frame| frame[:lineno] = lineno.to_i if lineno }
223
+ end
224
+
225
+ def parse_culprit_and_message(function, file_name_and_lineno)
226
+ @culprit = function
221
227
 
222
- @extra['crashed_thread_id'] = thread_id
228
+ message_tail = function
229
+ message_tail += " (#{file_name_and_lineno})" if file_name_and_lineno
230
+
231
+ if @message.nil?
232
+ @message = message_tail
233
+ else
234
+ # already parsed the crash reason
235
+ @message += " at #{message_tail}"
236
+ end
223
237
  end
224
238
 
225
239
  MODULE_LINE_REGEX = /0x[0-9a-f]+\s+-\s+0x[0-9a-f]+\s+([^ ]+)\s+([^ ]+)/
226
240
 
241
+ # rubocop:disable Metrics/LineLength
227
242
  # Parses something of the form
228
243
  # Loaded modules:
229
244
  # 0x00d70000 - 0x01b39fff ETClient.exe ??? (main)
@@ -278,6 +293,7 @@ module SentryBreakpad
278
293
  # 0x76f90000 - 0x76feffff imm32.dll 6.1.7601.17514
279
294
  # 0x76ff0000 - 0x77016fff cfgmgr32.dll 6.1.7601.17621
280
295
  # 0x77420000 - 0x7759ffff ntdll.dll 6.1.7601.19110 (WARNING: No symbols, wntdll.pdb, 992AA396746C4D548F7F497DD63B4EEC2)
296
+ # rubocop:enable Metrics/LineLength
281
297
  def parse_loaded_modules(lines)
282
298
  # remove the 1st line
283
299
  lines.pop
@@ -290,7 +306,7 @@ module SentryBreakpad
290
306
  end
291
307
  end
292
308
 
293
- def process_matching_lines(lines, regex, &blk)
309
+ def process_matching_lines(lines, regex, &_blk)
294
310
  loop do
295
311
  line = lines.pop
296
312
  line.strip! if line
@@ -301,19 +317,5 @@ module SentryBreakpad
301
317
  yield(match) if match
302
318
  end
303
319
  end
304
-
305
- # merges hash2 into hash1, recursively
306
- # wish ActiveSupport was around...
307
- def deep_merge(hash1, hash2)
308
- hash2.each do |key, value|
309
- if hash1.key?(value) && hash1[key].is_a?(Hash) && value.is_a?(Hash)
310
- hash1[key] = deep_merge(hash1[key], value)
311
- else
312
- hash1[key] = value
313
- end
314
- end
315
-
316
- hash1
317
- end
318
320
  end
319
321
  end
@@ -0,0 +1,30 @@
1
+ # Seemed somewhat silly to pull ActiveSupport as a dependency for just a couple
2
+ # of methods...
3
+
4
+ module SentryBreakpad
5
+ class HashHelper
6
+ class << self
7
+ # merges hash2 into hash1, recursively
8
+ def deep_merge!(hash1, hash2)
9
+ hash2.each do |key, value|
10
+ hash1[key] = if hash1.key?(key) && hash1[key].is_a?(Hash) && value.is_a?(Hash)
11
+ deep_merge!(hash1[key], value)
12
+ else
13
+ value
14
+ end
15
+ end
16
+
17
+ hash1
18
+ end
19
+
20
+ # recursively symbolizes a hash's keys
21
+ def deep_symbolize_keys!(hash)
22
+ hash.each_with_object({}) do |(key, value), new_hash|
23
+ new_key = key.respond_to?(:to_sym) ? key.to_sym : key
24
+ new_value = value.is_a?(Hash) ? deep_symbolize_keys!(value) : value
25
+ new_hash[new_key] = new_value
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module SentryBreakpad
2
- VERSION = "0.1.9"
2
+ VERSION = '0.1.10'.freeze
3
3
  end
@@ -4,21 +4,22 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'sentry_breakpad/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "sentry_breakpad"
8
- spec.version = SentryBreakpad::VERSION
9
- spec.authors = ["Jean Rouge"]
10
- spec.email = ["jer329@cornell.edu"]
7
+ spec.name = 'sentry_breakpad'
8
+ spec.version = SentryBreakpad::VERSION
9
+ spec.authors = ['Jean Rouge']
10
+ spec.email = ['jer329@cornell.edu']
11
11
 
12
- spec.summary = %q{Converts Google breakpad's reports into Sentry/Raven events}
13
- spec.homepage = "https://github.com/wk8/sentry_breakpad"
14
- spec.license = "MIT"
12
+ spec.summary = "Converts Google breakpad's reports into Sentry/Raven events"
13
+ spec.homepage = 'https://github.com/wk8/sentry_breakpad'
14
+ spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = "exe"
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
- spec.require_paths = ["lib"]
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = 'exe'
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency "sentry-raven", "~> 2.2.0"
21
+ spec.add_dependency 'sentry-raven', '~> 2.2.0'
22
22
 
23
- spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'rubocop'
24
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry_breakpad
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Rouge
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-12 00:00:00.000000000 Z
11
+ date: 2016-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sentry-raven
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description:
42
56
  email:
43
57
  - jer329@cornell.edu
@@ -47,8 +61,10 @@ extra_rdoc_files: []
47
61
  files:
48
62
  - ".gitignore"
49
63
  - ".rspec"
64
+ - ".rubocop.yml"
50
65
  - ".travis.yml"
51
66
  - Gemfile
67
+ - Gemfile.lock
52
68
  - LICENSE.txt
53
69
  - README.md
54
70
  - Rakefile
@@ -56,6 +72,7 @@ files:
56
72
  - bin/setup
57
73
  - lib/sentry_breakpad.rb
58
74
  - lib/sentry_breakpad/breakpad_parser.rb
75
+ - lib/sentry_breakpad/hash_helper.rb
59
76
  - lib/sentry_breakpad/version.rb
60
77
  - sentry_breakpad.gemspec
61
78
  homepage: https://github.com/wk8/sentry_breakpad