zaphod 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9716d2d2bc5d2523195132e42ef2cfe697956449
4
- data.tar.gz: 02e7e816192a3437b1a2c6b946ed6a97780bf018
3
+ metadata.gz: eb48ef706b22fe9a2b035380caf5f5e075a6044b
4
+ data.tar.gz: 53636ac34dabeba5d5e9216ce93158c824f7a566
5
5
  SHA512:
6
- metadata.gz: c96b73e834d184a91993a6f95f7a74bb101d7bc2763f1f4a99bcbbf1bf670fbcc8f34172b6fc06ff31365f2223fc6f3f62b750778ee7b91650921d7da95cb15d
7
- data.tar.gz: 7a4d12e3294f2e00b87ab66545f7e6ca9ffbd6ff2d29c10099c2bb5d460f27e28f2a71b2e973f8dd40ad4bafb281f09dd03ee34949705dd92d5fb844e4b07032
6
+ metadata.gz: 4648fbe942eb86ca77f630f6a9c31fd170a075a03105a0d134d407e629c009e905f0e120ef71de259d7f45f09ac5399bd2a521dd10ca5f644f10ffbf025df283
7
+ data.tar.gz: 27cb0eb96188fc4af4e0fa78e0fb44bb21d88d5850d73bc87ca584a8bf7b6848f8240579174fa462b79c4b6f8b76f181c1ad83ffe52c4c57f25051f311e2d289
data/.gitignore CHANGED
@@ -11,3 +11,4 @@ rdoc
11
11
  spec/reports
12
12
  .bundle
13
13
  .ruby-version
14
+ log/*
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- zaphod (1.0.1)
5
- grit (~> 2.5)
4
+ zaphod (1.1.0)
5
+ git (~> 1.2.6)
6
6
  simplecov (~> 0.8)
7
7
 
8
8
  GEM
@@ -15,11 +15,8 @@ GEM
15
15
  docile (1.1.2)
16
16
  ffi (1.9.3)
17
17
  formatador (0.2.4)
18
- grit (2.5.0)
19
- diff-lcs (~> 1.1)
20
- mime-types (~> 1.15)
21
- posix-spawn (~> 0.3.6)
22
- guard (2.3.0)
18
+ git (1.2.6)
19
+ guard (2.4.0)
23
20
  formatador (>= 0.2.4)
24
21
  listen (~> 2.1)
25
22
  lumberjack (~> 1.0)
@@ -33,16 +30,14 @@ GEM
33
30
  rspec (>= 2.14, < 4.0)
34
31
  guard-shell (0.6.1)
35
32
  guard (>= 1.1.0)
36
- listen (2.4.0)
33
+ listen (2.4.1)
37
34
  celluloid (>= 0.15.2)
38
35
  rb-fsevent (>= 0.9.3)
39
36
  rb-inotify (>= 0.9)
40
37
  lumberjack (1.0.4)
41
38
  method_source (0.8.2)
42
- mime-types (1.25.1)
43
39
  multi_json (1.8.4)
44
- posix-spawn (0.3.8)
45
- pry (0.9.12.4)
40
+ pry (0.9.12.6)
46
41
  coderay (~> 1.0)
47
42
  method_source (~> 0.8)
48
43
  slop (~> 3.4)
@@ -73,7 +68,7 @@ PLATFORMS
73
68
  ruby
74
69
 
75
70
  DEPENDENCIES
76
- guard (~> 2.3)
71
+ guard (~> 2.4)
77
72
  guard-bundler
78
73
  guard-rspec (~> 4.2)
79
74
  guard-shell
data/README.org CHANGED
@@ -6,6 +6,11 @@
6
6
 
7
7
  Catch, and publicly embarrass, untested commits into git.
8
8
 
9
+ Zaphod is a formatter for SimpleCov that compares the current git changes
10
+ with the uncovered source reported by SimpleCov. If any source code appears
11
+ both in the uncovered code and git changes, Zaphod will call an #on_failure
12
+ hook. By default, this exits and fails the build.
13
+
9
14
  ** Installation
10
15
 
11
16
  *** Simple Installation
@@ -15,6 +20,11 @@ Catch, and publicly embarrass, untested commits into git.
15
20
  Zaphod.setup
16
21
  #+END_SRC
17
22
 
23
+ This will set up the Zaphod formatter and start SimpleCov.
24
+
25
+ Be certain that SimpleCov is started before any of your project's source is loaded.
26
+
27
+
18
28
  *** Setup your own SimpleCov Formatters
19
29
 
20
30
  #+BEGIN_SRC ruby
@@ -34,12 +44,14 @@ Catch, and publicly embarrass, untested commits into git.
34
44
  require "pony"
35
45
 
36
46
  Zaphod.setup do |configuration|
37
- configuration.on_failure do
47
+ # Action to take if uncovered changes are found:
48
+ configuration.on_failure do |uncovered_changes|
38
49
  Pony.mail(
39
50
  to: 'your-team@example.com',
40
- subject: "Someone is trying to commit untested code!"
51
+ subject: "Someone is trying to commit untested code!",
52
+ body: uncovered_changes.to_s
41
53
  )
42
- raise SystemExit.new( -1 )
54
+ exit -1 # Abort the build with a failing exit code
43
55
  end
44
56
  end
45
57
  #+END_SRC
@@ -51,9 +63,16 @@ Catch, and publicly embarrass, untested commits into git.
51
63
  ]
52
64
 
53
65
  Zaphod.configure do |configuration|
54
- configuration.on_failure do
66
+ configuration.on_failure do |uncovered_changes|
55
67
  $stderr.puts "What would your mother think?"
68
+ exit -1
56
69
  end
57
70
  end
58
71
  SimpleCov.start
59
72
  #+END_SRC
73
+
74
+ ** Dependencies
75
+
76
+ - Grit
77
+ - SimpleCov
78
+
@@ -25,11 +25,13 @@ module SimpleCov
25
25
  if $DEBUG || ENV["DEBUG"]
26
26
  require "pp"
27
27
  pp(
28
- "--- UNCOVERED ---", uncovered_codeset,
29
- "--- CHANGED ---", changed_codeset,
30
- "--- DIFF ---", diff
28
+ "--- UNCOVERED ---", uncovered_codeset,
29
+ "--- CHANGED ---", changed_codeset,
30
+ "--- INTERSECTION ---"
31
31
  )
32
+ puts diff.to_s, "FAIL?: #{! diff.empty?}"
32
33
  end
34
+
33
35
  unless diff.empty?
34
36
  Zaphod.configuration.on_failure.call diff
35
37
  end
@@ -4,11 +4,11 @@ require "set"
4
4
  module Zaphod
5
5
  class ChangeSet
6
6
  extend Forwardable
7
- attr_reader :changes
7
+ attr_reader :changes, :user
8
8
  def_delegators :@changes, :empty?, :each, :map, :first, :length, :include?, :add, :any?
9
9
 
10
- def initialize( changes=[] )
11
- @changes = Set.new changes
10
+ def initialize( changes=[], user="unknown" )
11
+ @changes, @user = Set.new( changes ), user
12
12
  end
13
13
 
14
14
  def intersection( other )
@@ -20,5 +20,9 @@ module Zaphod
20
20
  def ==( other )
21
21
  changes == other.changes
22
22
  end
23
+
24
+ def to_s()
25
+ ["## #{user}", changes.map( &:to_s )].join "\n"
26
+ end
23
27
  end
24
28
  end
@@ -21,5 +21,9 @@ module Zaphod
21
21
  source.map( &:inspect ).join( ",\n" ) +
22
22
  "])"
23
23
  end
24
+
25
+ def to_s()
26
+ ["### #{path}", source.join].join "\n"
27
+ end
24
28
  end
25
29
  end
@@ -1,4 +1,5 @@
1
- require 'grit'
1
+ require "git"
2
+ require "logger"
2
3
 
3
4
  module Zaphod
4
5
  class Git
@@ -6,7 +7,7 @@ module Zaphod
6
7
  attr_accessor :diff_against
7
8
 
8
9
  def self.from_path( path )
9
- new Grit::Repo.new( path )
10
+ new ::Git.open( path, log: Logger.new( "log/zaphod-git.log" ) )
10
11
  end
11
12
 
12
13
  def initialize( repository, diff_against="HEAD" )
@@ -15,22 +16,33 @@ module Zaphod
15
16
  end
16
17
 
17
18
  def diff()
18
- diffs = repo.git.diff_index( { p: true }, diff_against ).
19
- split( /^diff --git .* b(.*)$/ )
20
-
19
+ path = repo.dir.path
20
+ diffs = repo.diff( diff_against, path )
21
21
  as_hash diffs
22
22
  end
23
23
 
24
+ def user()
25
+ config = repo.config
26
+ [config["user.name"], config["user.email"]].join " "
27
+ end
28
+
24
29
  protected
25
30
 
26
- def as_hash( diff )
27
- diffs = diff.drop_while( &:empty? )
28
- relativize_paths Hash[*diffs]
31
+ def as_hash( diffs )
32
+ pairs = diffs.flat_map { |diff_file|
33
+ [diff_file.path, additions( diff_file.patch )]
34
+ }
35
+ relativize_paths Hash[*pairs]
36
+ end
37
+
38
+ def additions( patch )
39
+ patch.lines.select { |l| l =~ /^[+][^+]/ }.
40
+ map { |l| l.gsub( /^[+]/, "" ) }
29
41
  end
30
42
 
31
43
  def relativize_paths( patch_map )
32
- patch_map.dup.each_with_object( map = {} ) do |pair, h|
33
- h[".#{pair.first}"] = pair.last
44
+ patch_map.each_with_object( map = {} ) do |pair, h|
45
+ h["./#{pair.first}"] = pair.last
34
46
  end
35
47
  map
36
48
  end
@@ -13,19 +13,10 @@ module Zaphod
13
13
  end
14
14
 
15
15
  def changes()
16
- ChangeSet.new repo.diff.map { |path, diff|
17
- CodeChange.new File.expand_path( path ), additions_from( diff.lines )
16
+ cc = repo.diff.map { |path, diff|
17
+ CodeChange.new File.expand_path( path ), diff
18
18
  }
19
- end
20
-
21
- def additions_from( lines )
22
- lines.
23
- select { |l| addition? l }.
24
- map { |l| l.gsub( /^[+]/, "" ) }
25
- end
26
-
27
- def addition?( line )
28
- line =~ /^[+][^+]/
19
+ ChangeSet.new cc, repo.user
29
20
  end
30
21
  end
31
22
  end
@@ -3,5 +3,11 @@ module Zaphod
3
3
  def initialize()
4
4
  @var = "foo"
5
5
  end
6
+
7
+
8
+ def untested_change!()
9
+ puts "untested!"
10
+ end
11
+
6
12
  end
7
13
  end
@@ -1,3 +1,3 @@
1
1
  module Zaphod
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -33,9 +33,14 @@ describe SimpleCov::Formatter::ZaphodFormatter do
33
33
  end
34
34
 
35
35
  before :each do
36
+ @original_failure = Zaphod.configuration.on_failure
36
37
  stub( source_control ).changes { source_changes }
37
38
  end
38
39
 
40
+ after :each do
41
+ Zaphod.configuration.on_failure &@original_failure
42
+ end
43
+
39
44
  it "runs the configured on_failure action, passing uncovered changes" do
40
45
  failed = false
41
46
  Zaphod.configure do |config|
@@ -1,7 +1,11 @@
1
1
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
2
-
3
2
  require 'zaphod'
4
- Zaphod.setup
3
+ Zaphod.setup do |config|
4
+ config.on_failure do
5
+ puts "Untested CHANGES!"
6
+ exit -1
7
+ end
8
+ end
5
9
 
6
10
  RSpec.configure do |config|
7
11
  config.treat_symbols_as_metadata_keys_with_true_values = true
@@ -20,6 +20,10 @@ module Zaphod
20
20
  it "rejects duplicates" do
21
21
  expect( described_class.new( changes ) ).to have( 1 ).item
22
22
  end
23
+
24
+ it "accepts a user string" do
25
+ described_class.new changes, "bob foo"
26
+ end
23
27
  end
24
28
 
25
29
  describe "iteration" do
@@ -84,5 +88,18 @@ module Zaphod
84
88
  end
85
89
  end
86
90
  end
91
+
92
+ describe "#to_s" do
93
+ subject( :set ) do
94
+ described_class.new([
95
+ CodeChange.new( "/dev/null", ["baz"] ),
96
+ CodeChange.new( "./lib/zaphod/spike.rb", ["foo"] )
97
+ ])
98
+ end
99
+
100
+ it do
101
+ expect( set.to_s ).to eq( ["## unknown", set.changes.map( &:to_s )].join( "\n" ) )
102
+ end
103
+ end
87
104
  end
88
105
  end
@@ -98,5 +98,26 @@ module Zaphod
98
98
  end
99
99
  end
100
100
 
101
+ describe "#to_s" do
102
+ subject( :change ) do
103
+ CodeChange.new(
104
+ "/app/controllers/tags_controller.rb", [
105
+ "\n",
106
+ " def uncovered_method\n",
107
+ " puts \"ha HA! I'm a cheater!\"\n",
108
+ " end\n"
109
+ ])
110
+ end
111
+
112
+ it do
113
+ expect( change.to_s ).to eq( <<EOS )
114
+ ### /app/controllers/tags_controller.rb
115
+
116
+ def uncovered_method
117
+ puts "ha HA! I'm a cheater!"
118
+ end
119
+ EOS
120
+ end
121
+ end
101
122
  end
102
123
  end
@@ -2,15 +2,21 @@ require 'spec_helper'
2
2
  require 'zaphod/git'
3
3
 
4
4
  describe Zaphod::Git do
5
- let( :git ) { stub!.diff_index { DIFF }.subject }
6
- let( :grit ) { stub!.git { git }.subject }
5
+ let( :path ) { "." }
6
+ let( :repo ) do
7
+ gitrb = Object.new
8
+ stub( gitrb ) do |allow|
9
+ allow.dir.stub!.path { path }
10
+ allow.diff( "HEAD", path ) { DIFF }
11
+ end
12
+ gitrb
13
+ end
7
14
 
8
- subject { described_class.new grit }
15
+ subject { described_class.new repo }
9
16
 
10
17
  describe "to get current changes in the git repository" do
11
- it "calls :diff_index on the Grit git object" do
12
- mock( git ).diff_index({ p: true }, "HEAD") { DIFF }
13
-
18
+ it "calls #diff on the Git repository object" do
19
+ mock( repo ).diff( "HEAD", "." ) { DIFF }
14
20
  subject.diff
15
21
  end
16
22
 
@@ -20,9 +26,41 @@ describe Zaphod::Git do
20
26
  "./spec/zaphod/source_control_spec.rb"
21
27
  )
22
28
  end
29
+
30
+ it "includes only the additions from the patch" do
31
+ additions = DIFF.first.patch.lines.select { |l| l =~ /^[+][^+]/ }
32
+ expect( subject.diff["./spec/spec_helper.rb"].size ).
33
+ to eq( additions.size )
34
+ end
35
+
36
+ it "strips the '+'" do
37
+ subject.diff.each do |path, additions|
38
+ expect( additions.all? { |l| ! l.start_with?( "+" ) } ).to be_true
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "#user" do
44
+ it "retrieves the user info from the git config" do
45
+ mock( repo ).config { Hash.new }
46
+ subject.user
47
+ end
48
+
49
+ it "returns the concatenation of the user name and email" do
50
+ stub( repo ).config do
51
+ {
52
+ "user.name" => "Bob Shlob",
53
+ "user.email" => "bob@mailinator.com"
54
+ }
55
+ end
56
+
57
+ expect( subject.user ).to eq( "Bob Shlob bob@mailinator.com" )
58
+ end
23
59
  end
24
60
 
25
- DIFF = <<-EOS
61
+ DiffFile = Struct.new :path, :patch
62
+ DIFF = [
63
+ DiffFile.new( "spec/spec_helper.rb", <<-EOS ),
26
64
  diff --git /dev/null b/spec/spec_helper.rb
27
65
  --- /dev/null
28
66
  +++ b/spec/spec_helper.rb
@@ -55,6 +93,8 @@ diff --git /dev/null b/spec/spec_helper.rb
55
93
  + # --seed 1234
56
94
  + config.order = 'random'
57
95
  +end
96
+ EOS
97
+ DiffFile.new( "spec/zaphod/source_control_spec.rb", <<-EOS ),
58
98
  diff --git a/spec/zaphod/source_control_spec.rbf b/spec/zaphod/source_control_spec.rb
59
99
  index 73d4e77..8ef378d 100644
60
100
  --- a/spec/zaphod/source_control_spec.rb
@@ -80,5 +120,6 @@ index 73d4e77..8ef378d 100644
80
120
  + let( :repository ) { stub git: git_native }
81
121
 
82
122
  let( :git ) { described_class.new repository }
83
- EOS
123
+ EOS
124
+ ]
84
125
  end
@@ -8,18 +8,25 @@ describe Zaphod::SourceControl do
8
8
 
9
9
  describe "#initialize" do
10
10
  it "accepts a repository" do
11
- described_class.new Grit::Repo.new REPO_PATH
11
+ described_class.new Git.open( REPO_PATH )
12
12
  end
13
13
  end
14
14
 
15
15
  describe "#changes" do
16
16
  let( :patch_map ) do
17
17
  {
18
- "./spec/spec_helper.rb" => "+ require 'rspec'\n",
19
- "./spec/zaphod/source_control_spec.rb" => "+ require 'spec_helper'\n"
18
+ "./spec/spec_helper.rb" => "require 'rspec'\n",
19
+ "./spec/zaphod/source_control_spec.rb" => "require 'spec_helper'\n"
20
20
  }
21
21
  end
22
- let( :repository ) { stub!.diff { patch_map }.subject }
22
+ let( :repository ) do
23
+ repo = Object.new
24
+ stub( repo ) do |allow|
25
+ allow.diff { patch_map }
26
+ allow.user { "bob smith smith@mailinator.com" }
27
+ end
28
+ repo
29
+ end
23
30
 
24
31
  subject { described_class.new repository }
25
32
 
@@ -38,12 +45,12 @@ describe Zaphod::SourceControl do
38
45
 
39
46
  it "passes the additions to each code set" do
40
47
  subject.changes.first.source.length.should eq(
41
- patch_map["./spec/spec_helper.rb"].lines.select { |l| l =~ /^[+][^+]/ }.to_a.size
48
+ patch_map["./spec/spec_helper.rb"].length
42
49
  )
43
50
  end
44
51
 
45
- it "strips the plusses off the lines" do
46
- subject.changes.first.source.first.should_not start_with( "+" )
52
+ it "provides the change set with the name of the alleged slacker" do
53
+ expect( subject.changes.user ).to eq( "bob smith smith@mailinator.com" )
47
54
  end
48
55
  end
49
56
  end
@@ -19,14 +19,14 @@ Gem::Specification.new do |spec|
19
19
  spec.extra_rdoc_files = %w[README.org]
20
20
  spec.rdoc_options = ["--charset=UTF-8"]
21
21
 
22
- spec.add_dependency "grit", "~> 2.5"
22
+ spec.add_dependency "git", "~> 1.2.6"
23
23
  spec.add_dependency "simplecov", "~> 0.8"
24
24
 
25
25
  spec.add_development_dependency "rake", "~> 10.1"
26
26
  spec.add_development_dependency "rr", "~> 1.1"
27
27
  spec.add_development_dependency "rspec", "~> 2.14"
28
28
  spec.add_development_dependency "pry"
29
- spec.add_development_dependency "guard", "~> 2.3"
29
+ spec.add_development_dependency "guard", "~> 2.4"
30
30
  spec.add_development_dependency "guard-rspec", "~> 4.2"
31
31
  spec.add_development_dependency "guard-bundler"
32
32
  spec.add_development_dependency "guard-shell"
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zaphod
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toby Tripp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-05 00:00:00.000000000 Z
11
+ date: 2014-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: grit
14
+ name: git
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.5'
19
+ version: 1.2.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.5'
26
+ version: 1.2.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: simplecov
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '2.3'
103
+ version: '2.4'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '2.3'
110
+ version: '2.4'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: guard-rspec
113
113
  requirement: !ruby/object:Gem::Requirement