git-swear-stats 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/LICENSE +14 -0
  2. data/README.md +44 -0
  3. data/Rakefile +3 -0
  4. data/bin/git-swear-stats +155 -0
  5. metadata +93 -0
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2
+ Version 2, December 2004
3
+
4
+ Copyright (C) 2013 James Pearson
5
+
6
+ Everyone is permitted to copy and distribute verbatim or modified
7
+ copies of this license document, and changing it is allowed as long
8
+ as the name is changed.
9
+
10
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
+
13
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
14
+
@@ -0,0 +1,44 @@
1
+ Inspired by [the Linux Kernel Fuck Count] and [its descendent],
2
+ `git-swear-stats` will give you some interesting statistics on swearing in a
3
+ git repository's commit messages.
4
+
5
+ [the Linux Kernel Fuck Count]: http://durak.org/sean/pubs/kfc/
6
+ [its descendent]: http://www.vidarholen.net/contents/wordcount/
7
+
8
+ # Installation
9
+
10
+ [$]> gem install git-swear-stats
11
+
12
+ # Usage
13
+
14
+ [$]> git-swear-stats --help
15
+ git-swear-stats
16
+
17
+ Usage:
18
+ git-swear-stats [options] [messages|diffs]
19
+
20
+ Options:
21
+ -h, --help Show this screen.
22
+ --debug Print out debug messages.
23
+ --include-merges Look at merge commits.
24
+ --no-progress Don't print out progress information.
25
+
26
+ # Example Output
27
+
28
+ [$]> git swear-stats
29
+ Reading in git log... done!
30
+ Parsing git log.
31
+ Overall:
32
+ +-------------+------+------+-----+------+------+------+-----+------+-------+-----+-----+------+---------+------+
33
+ | clusterfuck | fuck | fsck | eff | shit | cunt | cock | ass | arse | bitch | wtf | fag | damn | bastard | hell |
34
+ +-------------+------+------+-----+------+------+------+-----+------+-------+-----+-----+------+---------+------+
35
+ | 1 | 3 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 3 | 1 | 1 | 1 | 1 |
36
+ +-------------+------+------+-----+------+------+------+-----+------+-------+-----+-----+------+---------+------+
37
+ Authors:
38
+ +---------------+-------------+------+------+-----+------+------+------+-----+------+-------+-----+-----+------+---------+------+
39
+ | | clusterfuck | fuck | fsck | eff | shit | cunt | cock | ass | arse | bitch | wtf | fag | damn | bastard | hell |
40
+ +---------------+-------------+------+------+-----+------+------+------+-----+------+-------+-----+-----+------+---------+------+
41
+ | xiongchiamiov | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
42
+ | James Pearson | 1 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
43
+ +---------------+-------------+------+------+-----+------+------+------+-----+------+-------+-----+-----+------+---------+------+
44
+
@@ -0,0 +1,3 @@
1
+ require 'mg'
2
+ MG.new 'git-swear-stats.gemspec'
3
+
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # May you recognize your weaknesses and share your strengths.
5
+ # May you share freely, never taking more than you give.
6
+ # May you find love and love everyone you find.
7
+
8
+ require 'docopt'
9
+ require 'git'
10
+ require 'pp'
11
+ require 'terminal-table'
12
+
13
+ # Git intercepts `git swear-stats --help`, so unfortunately most people won't
14
+ # see this usage message. Docopt is still a great way to do parsing, though.
15
+ doc = <<DOCOPT
16
+ git-swear-stats
17
+
18
+ Usage:
19
+ git-swear-stats [options] [messages|diffs]
20
+
21
+ Options:
22
+ -h, --help Show this screen.
23
+ --debug Print out debug messages.
24
+ --include-merges Look at merge commits.
25
+ --no-progress Don't print out progress information.
26
+
27
+ DOCOPT
28
+ begin
29
+ options = Docopt::docopt doc
30
+ rescue Docopt::Exit => e
31
+ puts e.message
32
+ exit 1
33
+ end
34
+ pp options if options['--debug']
35
+
36
+ swears = [
37
+ %r{^(dip)?shit(ty)?$},
38
+ %r{^(cluster|mother)?(fuck|fsck|eff)(ing|er|ed|head)?$},
39
+ %r{^cunt$},
40
+ %r{^cock(suck|sucker)?$},
41
+ %r{^(ass|arse)(hole)?$},
42
+ %r{^bitch(y)?$},
43
+ %r{^wtf$},
44
+ %r{^fag(got)?$},
45
+ %r{^(god)?damn(ed|able)?$},
46
+ %r{^bastard$},
47
+ %r{^hell(ish)?$},
48
+ ]
49
+ wordDelimiters = %r{[ \-_.,!?;:*"'|{}()\n]}
50
+
51
+ wordStats = {}
52
+ wordStats.default = 0
53
+ authorStats = {}
54
+
55
+ repo = Git.open '.'
56
+ # By default, we only get up to 30 commits in the log. By digging through the
57
+ # source, I found that passing nil to repo.log() ends up setting the limit to
58
+ # nil, and thus giving us all commits.
59
+ print 'Reading in git log... ' if not options['--no-progress']
60
+ log = repo.log nil
61
+ puts 'done!' if not options['--no-progress']
62
+
63
+ print 'Parsing git log' if not options['--no-progress']
64
+ log.each_with_index do |commit, i|
65
+ # Merges often have data in them from other commits, pull request
66
+ # descriptions, etc., so it's not really fair to count them.
67
+ # Git::Log unfortunately appears to have no way of passing --no-merges
68
+ # through to the underlying binary, so we have to check merges on a
69
+ # commit-by-commit basis instead.
70
+ next if not options['--include-merges'] and commit.parents.count > 1
71
+
72
+ author = commit.author.name
73
+ if not authorStats.key? author
74
+ authorStats[author] = {}
75
+ authorStats[author].default = 0
76
+ end
77
+
78
+ if !options['diffs']
79
+ # Splitting on words makes our regexes a little simpler.
80
+ commit.message.split(wordDelimiters).each do |word|
81
+ word.downcase! # A little bit of normalization.
82
+ swears.each do |swear|
83
+ if word =~ swear
84
+ wordStats[word] += 1
85
+ authorStats[author][word] += 1
86
+ if options['--debug']
87
+ puts '-'*80
88
+ puts author
89
+ puts commit.message
90
+ puts '-'*80
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ if !options['messages']
98
+ # The git module doesn't handle a diff on the initial commit very well - by
99
+ # which I mean it throws an exception.
100
+ # TODO: Monkeypatch the shit out of Git::Commit.
101
+ next if commit.parents.count == 0
102
+
103
+ diff = commit.diff_parent.to_s.force_encoding 'iso-8859-1'
104
+ # We only want to look at stuff they did, not surrounding things. We'll
105
+ # approximate this by grepping through lines "added".
106
+ lines = diff.split("\n")
107
+ # Drop the first four lines to get rid of the diff header.
108
+ lines.drop(4).keep_if {|line| line =~ /^\+/}.each do |line|
109
+ line[1..-1].split(wordDelimiters).each do |word|
110
+ word.downcase! # A little bit of normalization.
111
+ swears.each do |swear|
112
+ if word =~ swear
113
+ wordStats[word] += 1
114
+ authorStats[author][word] += 1
115
+ if options['--debug']
116
+ puts '-'*80
117
+ puts author
118
+ puts line
119
+ puts '-'*80
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ # For large repos, parsing can take a while; let users know something is
128
+ # happening.
129
+ print '.' if i % 100 == 0 and not options['--no-progress']
130
+ end
131
+ puts if not options['--no-progress']
132
+
133
+ # People who haven't sworn at all aren't very interesting.
134
+ authorStats.delete_if {|author, swears| swears.empty?}
135
+
136
+ pp wordStats if options['--debug']
137
+ pp authorStats if options['--debug']
138
+
139
+ puts 'Overall:'
140
+ table = Terminal::Table.new
141
+ table.headings = wordStats.keys
142
+ table.add_row wordStats.values
143
+ puts table
144
+
145
+ puts 'Authors:'
146
+ table = Terminal::Table.new
147
+ table.headings = header = [''] + wordStats.keys
148
+ authorStats.each do |author, stats|
149
+ row = []
150
+ stats[''] = author # Cheat a little for the first column.
151
+ header.each {|swear| row << stats[swear]}
152
+ table.add_row row
153
+ end
154
+ puts table
155
+
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git-swear-stats
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - James Pearson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2013-03-24 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: docopt
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: git
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: terminal-table
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ description: Gather statistics on swearing in a repo.
50
+ email:
51
+ - xiong.chiamiov@gmail.com
52
+ executables:
53
+ - git-swear-stats
54
+ extensions: []
55
+
56
+ extra_rdoc_files:
57
+ - LICENSE
58
+ - README.md
59
+ files:
60
+ - LICENSE
61
+ - Rakefile
62
+ - README.md
63
+ - bin/git-swear-stats
64
+ has_rdoc: true
65
+ homepage: https://github.com/xiongchiamiov/git-swear-stats
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.5.3
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Gather statistics on swearing in a repo.
92
+ test_files: []
93
+