bugwatch 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bugwatch.gemspec ADDED
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2013, Groupon, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of GROUPON nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ Gem::Specification.new do |s|
32
+ s.name = 'bugwatch'
33
+ s.version = '0.1'
34
+ s.date = '2012-02-13'
35
+
36
+ s.summary = 'bugwatch'
37
+ s.description = 'SCM history mining and code analysis platform'
38
+
39
+ s.authors = ['Jacob Richardson']
40
+ s.email = 'jacobr@groupon.com'
41
+
42
+ s.require_paths = %w[lib]
43
+
44
+ s.add_dependency('grit', '2.5.0')
45
+ s.add_dependency('ruby_parser', '~> 3.0.1')
46
+ s.add_dependency('rugged', '0.16.2')
47
+
48
+ # = MANIFEST =
49
+ s.files = %w[
50
+ bugwatch.gemspec
51
+ lib/bugwatch.rb
52
+ lib/bugwatch/adapters.rb
53
+ lib/bugwatch/analysis.rb
54
+ lib/bugwatch/attrs.rb
55
+ lib/bugwatch/churn.rb
56
+ lib/bugwatch/commit.rb
57
+ lib/bugwatch/complexity_score.rb
58
+ lib/bugwatch/diff.rb
59
+ lib/bugwatch/diff_parser.rb
60
+ lib/bugwatch/exception_data.rb
61
+ lib/bugwatch/exception_tracker.rb
62
+ lib/bugwatch/file_adapters/ruby_file_adapter.rb
63
+ lib/bugwatch/flog_score.rb
64
+ lib/bugwatch/import.rb
65
+ lib/bugwatch/method_parser.rb
66
+ lib/bugwatch/repo.rb
67
+ lib/bugwatch/ruby_complexity.rb
68
+ lib/bugwatch/tag.rb
69
+ lib/bugwatch/tree.rb
70
+ vendor/flog/lib/flog.rb
71
+ ]
72
+ # = MANIFEST =
73
+
74
+ end
data/lib/bugwatch.rb ADDED
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2013, Groupon, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of GROUPON nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'rugged'
32
+ require 'grit'
33
+
34
+ require File.expand_path('../bugwatch/adapters', __FILE__)
35
+ require File.expand_path('../bugwatch/analysis', __FILE__)
36
+ require File.expand_path('../bugwatch/attrs', __FILE__)
37
+ require File.expand_path('../bugwatch/complexity_score', __FILE__)
38
+ require File.expand_path('../bugwatch/diff_parser', __FILE__)
39
+ require File.expand_path('../bugwatch/ruby_complexity', __FILE__)
40
+ require File.expand_path('../bugwatch/churn', __FILE__)
41
+ require File.expand_path('../bugwatch/commit', __FILE__)
42
+ require File.expand_path('../bugwatch/diff', __FILE__)
43
+ require File.expand_path('../bugwatch/exception_data', __FILE__)
44
+ require File.expand_path('../bugwatch/exception_tracker', __FILE__)
45
+ require File.expand_path('../bugwatch/flog_score', __FILE__)
46
+ require File.expand_path('../bugwatch/import', __FILE__)
47
+ require File.expand_path('../bugwatch/method_parser', __FILE__)
48
+ require File.expand_path('../bugwatch/repo', __FILE__)
49
+ require File.expand_path('../bugwatch/tag', __FILE__)
50
+ require File.expand_path('../bugwatch/tree', __FILE__)
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2013, Groupon, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of GROUPON nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'bugwatch/file_adapters/ruby_file_adapter'
32
+ require 'bugwatch/ruby_complexity'
33
+
34
+ module Bugwatch
35
+
36
+ Adapter = Struct.new(:file, :complexity)
37
+
38
+ @adapters = {
39
+ ruby: Adapter.new(RubyFileAdapter, RubyComplexity)
40
+ }
41
+
42
+ def self.add_adapter(name, file_adapter, complexity=nil)
43
+ @adapters.merge!(name => Adapter.new(file_adapter, complexity))
44
+ end
45
+
46
+ def self.adapters
47
+ @adapters
48
+ end
49
+
50
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright (c) 2013, Groupon, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of GROUPON nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ module Bugwatch
32
+
33
+ class Analysis
34
+
35
+ def initialize(repo, caching_strategy)
36
+ @repo = repo
37
+ @caching_strategy = caching_strategy
38
+ end
39
+
40
+ def analyze(*analyzers)
41
+ analyzers.each do |analyzer|
42
+ commits_to_analyze(analyzer).each do |commit_sha|
43
+ commit = @repo.commit(commit_sha)
44
+ analyzer.call(commit)
45
+ @caching_strategy.store_analysis(commit, analyzer.key)
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def commits_to_analyze(analyzer)
53
+ @caching_strategy.imported - @caching_strategy.analyzed(analyzer.key)
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,64 @@
1
+ # Copyright (c) 2013, Groupon, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of GROUPON nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ module Bugwatch
32
+
33
+ module Attrs
34
+
35
+ def attrs(*attributes)
36
+ define_attr_reader(attributes) do |attr|
37
+ attr
38
+ end
39
+ end
40
+
41
+ def lazy_attrs(*attributes)
42
+ define_attr_reader(attributes) do |attr|
43
+ if attr.respond_to? :call
44
+ attr.call
45
+ else
46
+ attr
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def define_attr_reader(attributes, &block)
54
+ attributes.each do |attribute|
55
+ define_method(attribute) do
56
+ data = instance_variable_get('@attributes') || {}
57
+ block.call(data[attribute])
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,60 @@
1
+ # Copyright (c) 2013, Groupon, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of GROUPON nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ module Bugwatch
32
+
33
+ class Churn
34
+
35
+ DEFAULT_CHURN = 0
36
+
37
+ def initialize(commit_stats, file_adapter)
38
+ @commit_stats = commit_stats
39
+ @file_adapter = file_adapter
40
+ end
41
+
42
+ def score
43
+ calculate_churn(&@file_adapter.method(:analyzable_file?))
44
+ end
45
+
46
+ def test_score
47
+ calculate_churn(&@file_adapter.method(:test_file?))
48
+ end
49
+
50
+ private
51
+
52
+ def calculate_churn(&filter)
53
+ @commit_stats.select do |stat|
54
+ filter.call(stat.file)
55
+ end.map(&:total).reduce(:+) || DEFAULT_CHURN
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,82 @@
1
+ # Copyright (c) 2013, Groupon, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions
6
+ # are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of GROUPON nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ module Bugwatch
32
+
33
+ class Commit
34
+
35
+ include RubyFileAdapter
36
+ extend Attrs
37
+
38
+ Stats = Struct.new(:file, :additions, :deletions, :total)
39
+
40
+ def self.from_grit(grit)
41
+ author = grit.author
42
+ committer = grit.committer
43
+ stats = Enumerator.new {|y| grit.stats.files.each {|data| y << Stats.new(*data) } }
44
+ diffs = Enumerator.new {|y| grit.diffs.each {|diff| y << Diff.from_grit(diff) } }
45
+ tree = Tree.new(grit.tree)
46
+ new sha: grit.sha, message: grit.short_message, diffs: diffs, stats: stats, tree: tree,
47
+ author_name: author.name, author_email: author.email, authored_date: grit.authored_date,
48
+ committer_name: committer.name, committer_email: committer.email, committed_date: grit.committed_date
49
+ end
50
+
51
+ def initialize(attributes={})
52
+ @attributes = attributes
53
+ end
54
+
55
+ attrs :sha, :message, :diffs, :stats
56
+ attrs :author_name, :author_email, :authored_date
57
+ attrs :committer_name, :committer_email, :committed_date
58
+ lazy_attrs :tree
59
+
60
+ def files
61
+ @files ||= stats.map(&:file)
62
+ end
63
+
64
+ def complexity(lang=:ruby)
65
+ adapter = Bugwatch.adapters[lang]
66
+ adapter.complexity.new(diffs) if adapter && adapter.complexity
67
+ end
68
+
69
+ def churn(lang=:ruby)
70
+ adapter = Bugwatch.adapters[lang]
71
+ Churn.new(stats, adapter.file) if adapter
72
+ end
73
+
74
+ # TODO don't use grit blob
75
+ def identify(filename, line_number)
76
+ blob = tree / filename
77
+ blob ? MethodParser.find(blob.data, line_number..line_number) : {}
78
+ end
79
+
80
+ end
81
+
82
+ end