fit-commit 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 81b67790de7d999eae5047a8acb714c14257f91d
4
+ data.tar.gz: 57e990996a4c9e9d704d483730cbc85ce2b46e65
5
+ SHA512:
6
+ metadata.gz: 621591bb43cd64e82dd41161c3375bf6bdabc1a3487899151e52837bbee44cbf149a030529d3a1129632c88609e75e9e5cd4ec01fa054b21e3240efbcf096e50
7
+ data.tar.gz: abb255557aa5b523d4ee9fa21eb1a46dd48362013536f3d93dc54d850032589bcf56fbf76311d1a7c4db3287f1324ef1532e9d6dead1496eef718add794615ec
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+ /bin/
12
+
13
+ ## Environment normalisation:
14
+ /.bundle/
15
+ /vendor/bundle
16
+ /lib/bundler/man/
17
+
18
+ # for a library or gem, you might want to ignore these files since the code is
19
+ # intended to run in multiple environments; otherwise, check them in:
20
+ # Gemfile.lock
21
+ # .ruby-version
22
+ # .ruby-gemset
23
+
24
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
25
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fit-commit (1.0.0)
5
+ swearjar (~> 1.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ fuzzyhash (0.0.11)
11
+ minitest (5.8.0)
12
+ rake (10.4.2)
13
+ swearjar (1.0.0)
14
+ fuzzyhash (~> 0.0.11)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ fit-commit!
21
+ minitest (~> 5.8)
22
+ rake (~> 10.4)
23
+
24
+ BUNDLED WITH
25
+ 1.10.6
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Mike Foley
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Fit Commit
2
+
3
+ A Git hook to validate your commit messages, based largely on Tim Pope's [authoritative guide](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
4
+
5
+ ## Example
6
+
7
+ ```
8
+ $ git commit
9
+ Adding a cool feature
10
+ foobar foobar foobar,
11
+ foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar
12
+
13
+ 1: Error: Message must use present imperative tense.
14
+ 2: Error: Second line must be blank.
15
+ 3: Error: Lines should be <= 72 chars. (76)
16
+
17
+ Force commit? [y/n] ▊
18
+ ```
19
+
20
+ ## Prerequisites
21
+
22
+ * Ruby
23
+
24
+ ## Installation
25
+
26
+ Install the gem:
27
+
28
+ $ gem install fit-commit
29
+
30
+ Install the hook in your Git repo:
31
+
32
+ $ fit-commit install
33
+
34
+ This creates a `.git/hooks/commit-msg` script which will automatically check your Git commit messages.
35
+
36
+ ## Validations
37
+
38
+ * **Line Length**: All lines must be <= 72 chars (URLs excluded). First line should be <= 50 chars. Second line must be blank.
39
+ * **Tense**: Message must use present imperative tense.
40
+ * **Summary Period**: Do not end your summary with a period.
41
+ * **WIP**: Do not commit WIPs to master.
42
+ * **Frat House**: No frat house commit messages in master.
43
+
44
+ ## Credits
45
+
46
+ Author: [Mike Foley](https://github.com/m1foley)
47
+
48
+ Inspiration taken from: [Tim Pope](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), [Jason Fox](https://gist.github.com/jasonrobertfox/8057124), [Addam Hardy](http://addamhardy.com/blog/2013/06/05/good-commit-messages-and-enforcing-them-with-git-hooks/), [pre-commit](https://github.com/jish/pre-commit)
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |test|
5
+ test.libs << "test"
6
+ test.pattern = "test/**/*_test.rb"
7
+ test.verbose = false
8
+ end
9
+
10
+ task :default => :test
data/TODO.txt ADDED
@@ -0,0 +1 @@
1
+ - Configuration to disable validations.
data/bin/fit-commit ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fit-commit/cli'
4
+
5
+ if !File.exists?(".git")
6
+ abort "No .git directory found."
7
+ end
8
+
9
+ FitCommit::Cli.new(*ARGV).execute or exit 1
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/fit-commit/version", __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "fit-commit"
6
+ gem.version = FitCommit::VERSION
7
+ gem.license = "MIT"
8
+ gem.authors = ["Michael Foley"]
9
+ gem.email = ["foley3@gmail.com"]
10
+ gem.homepage = "https://github.com/m1foley/fit-commit"
11
+ gem.summary = "A Git hook to validate your commit messages"
12
+ gem.description = "A Git hook to validate your commit messages, based largely on Tim Pope's authoritative guide."
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.executables = ["fit-commit"]
15
+ gem.default_executable = "fit-commit"
16
+ gem.test_files = `git ls-files -- test/*`.split("\n")
17
+ gem.require_paths = ["lib"]
18
+ gem.extra_rdoc_files = ["README.md"]
19
+ gem.rdoc_options = ["--main", "README.md"]
20
+
21
+ gem.post_install_message == <<-EOF
22
+ Thank you for installing fit-commit!
23
+ Install the hook in each git repo you want to scan using:
24
+
25
+ > fit-commit install
26
+
27
+ Read more: https://github.com/m1foley/fit-commit#readme
28
+ EOF
29
+
30
+ gem.add_dependency("swearjar", "~> 1.0")
31
+ gem.add_development_dependency("minitest", "~> 5.8")
32
+ gem.add_development_dependency("rake", "~> 10.4")
33
+ end
@@ -0,0 +1,20 @@
1
+ require "fit-commit/installer"
2
+
3
+ module FitCommit
4
+ class Cli
5
+ attr_accessor :args
6
+ def initialize(*args)
7
+ self.args = args
8
+ end
9
+
10
+ def execute
11
+ action_name = args.shift
12
+ if action_name == "install"
13
+ FitCommit::Installer.new.install
14
+ else
15
+ warn "Usage: fit-commit install"
16
+ false
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,36 @@
1
+ # Mixin for adding errors & warnings
2
+ module FitCommit
3
+ module HasErrors
4
+ def errors
5
+ @errors ||= Hash.new([])
6
+ end
7
+
8
+ def warnings
9
+ @warnings ||= Hash.new([])
10
+ end
11
+
12
+ def add_error(lineno, message)
13
+ errors[lineno] += [message]
14
+ end
15
+
16
+ def add_warning(lineno, message)
17
+ warnings[lineno] += [message]
18
+ end
19
+
20
+ def merge_errors(other_errors)
21
+ merge_hashes(errors, other_errors)
22
+ end
23
+
24
+ def merge_warnings(other_warnings)
25
+ merge_hashes(warnings, other_warnings)
26
+ end
27
+
28
+ private
29
+
30
+ def merge_hashes(error_hash, other_hash)
31
+ error_hash.merge!(other_hash) do |_lineno, messages, other_messages|
32
+ messages + other_messages
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,29 @@
1
+ require "fileutils"
2
+
3
+ module FitCommit
4
+ class Installer
5
+ HOOK_TEMPLATE_PATH = File.expand_path("../../../templates/hooks/commit-msg", __FILE__)
6
+
7
+ def install
8
+ FileUtils.mkdir_p(File.dirname(hook_path))
9
+ FileUtils.cp(HOOK_TEMPLATE_PATH, hook_path)
10
+ FileUtils.chmod(0755, hook_path)
11
+ puts "Installed hook to #{hook_path}"
12
+ true
13
+ end
14
+
15
+ private
16
+
17
+ def hook_path
18
+ @hook_path ||= File.join(gitdir, "hooks/commit-msg")
19
+ end
20
+
21
+ def gitdir
22
+ if File.directory?(".git")
23
+ ".git"
24
+ else
25
+ File.readlines(".git").first.match(/gitdir: (.*)$/)[1]
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ # Represents a line from the commit
2
+ module FitCommit
3
+ class Line
4
+ attr_accessor :lineno, :text
5
+ def initialize(lineno, text)
6
+ self.lineno = lineno
7
+ self.text = text
8
+ end
9
+
10
+ def to_s
11
+ text
12
+ end
13
+
14
+ def empty?
15
+ text.empty?
16
+ end
17
+
18
+ def self.from_array(text_array)
19
+ text_array.map.with_index(1) { |text, lineno| new(lineno, text) }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,83 @@
1
+ require "fit-commit/has_errors"
2
+ require "fit-commit/line"
3
+
4
+ module FitCommit
5
+ class Runner
6
+ include FitCommit::HasErrors
7
+
8
+ attr_accessor :message_path, :branch_name, :stdout, :stdin
9
+ def initialize(message_path, branch_name, stdout = $stdout, stdin = $stdin)
10
+ self.message_path = message_path
11
+ self.branch_name = branch_name
12
+ self.stdout = stdout
13
+ self.stdin = stdin
14
+ end
15
+
16
+ def run
17
+ return true if empty_commit?
18
+ run_validators
19
+ return true if [errors, warnings].all?(&:empty?)
20
+ print_results
21
+
22
+ allow_commit = errors.empty?
23
+ unless allow_commit
24
+ stdout.print "\nForce commit? [y/n] "
25
+ return false unless stdin.gets =~ /y/i
26
+ allow_commit = true
27
+ end
28
+
29
+ stdout.print "\n"
30
+ allow_commit
31
+ rescue Interrupt # Ctrl-c
32
+ false
33
+ end
34
+
35
+ private
36
+
37
+ def run_validators
38
+ Dir[File.dirname(__FILE__) + "/validators/*.rb"].each { |file| require file }
39
+ FitCommit::Validators::Base.all.each do |validator_class|
40
+ validator = validator_class.new(lines, branch_name)
41
+ validator.validate
42
+ merge_errors(validator.errors)
43
+ merge_warnings(validator.warnings)
44
+ end
45
+ end
46
+
47
+ def print_results
48
+ unless errors.empty?
49
+ stdout.puts lines
50
+ stdout.print "\n"
51
+ end
52
+
53
+ (errors.keys | warnings.keys).sort.each do |lineno|
54
+ errors[lineno].each do |error|
55
+ stdout.puts "#{lineno}: Error: #{error}"
56
+ end
57
+ warnings[lineno].each do |warning|
58
+ stdout.puts "#{lineno}: Warning: #{warning}"
59
+ end
60
+ end
61
+ end
62
+
63
+ def lines
64
+ @lines ||= FitCommit::Line.from_array(relevant_message_lines)
65
+ end
66
+
67
+ def relevant_message_lines
68
+ message_text.lines.map(&:chomp).reject(&method(:comment?))
69
+ end
70
+
71
+ def message_text
72
+ File.open(message_path, "r").read
73
+ end
74
+
75
+ def comment?(text)
76
+ text =~ /\A#/
77
+ end
78
+
79
+ def empty_commit?
80
+ lines.all?(&:empty?)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,33 @@
1
+ require "fit-commit/has_errors"
2
+
3
+ module FitCommit
4
+ module Validators
5
+ class Base
6
+ include FitCommit::HasErrors
7
+
8
+ attr_accessor :lines, :branch_name
9
+ def initialize(lines, branch_name)
10
+ self.lines = lines
11
+ self.branch_name = branch_name
12
+ end
13
+
14
+ @all = []
15
+ class << self
16
+ attr_accessor :all
17
+ def inherited(subclass)
18
+ all << subclass
19
+ end
20
+ end
21
+
22
+ def validate
23
+ lines.each do |line|
24
+ validate_line(line.lineno, line.text, branch_name)
25
+ end
26
+ end
27
+
28
+ def validate_line(*)
29
+ fail NotImplementedError, "Implement in subclass"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ require "fit-commit/validators/base"
2
+ require "swearjar"
3
+
4
+ module FitCommit
5
+ module Validators
6
+ class Frathouse < Base
7
+ def validate_line(lineno, text, branch_name)
8
+ if branch_name == "master" && Swearjar.default.profane?(text)
9
+ add_error(lineno, "No frat house commit messages in master.")
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ require "fit-commit/validators/base"
2
+
3
+ module FitCommit
4
+ module Validators
5
+ class LineLength < Base
6
+ FIRST_LINE_MAX_LENGTH = 50
7
+ LINE_MAX_LENGTH = 72
8
+
9
+ def validate_line(lineno, text, _branch_name)
10
+ if lineno == 1 && text.empty?
11
+ add_error(lineno, "First line cannot be blank.")
12
+ elsif lineno == 2 && !text.empty?
13
+ add_error(lineno, "Second line must be blank.")
14
+ elsif line_too_long?(text)
15
+ add_error(lineno, format("Lines should be <= %i chars. (%i)",
16
+ LINE_MAX_LENGTH, text.length))
17
+ elsif lineno == 1 && text.length > FIRST_LINE_MAX_LENGTH
18
+ add_warning(lineno, format("First line should be <= %i chars. (%i)",
19
+ FIRST_LINE_MAX_LENGTH, text.length))
20
+ end
21
+ end
22
+
23
+ def line_too_long?(text)
24
+ text.length > 72 && !contains_url?(text)
25
+ end
26
+
27
+ def contains_url?(text)
28
+ text =~ %r{[a-z]+://}
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ require "fit-commit/validators/base"
2
+
3
+ module FitCommit
4
+ module Validators
5
+ class SummaryPeriod < Base
6
+ def validate_line(lineno, text, branch_name)
7
+ if lineno == 1 && text.end_with?(".")
8
+ add_error(lineno, "Do not end your summary with a period.")
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,78 @@
1
+ require "fit-commit/validators/base"
2
+
3
+ module FitCommit
4
+ module Validators
5
+ class Tense < Base
6
+ VERB_BLACKLIST = %w(
7
+ adds adding added
8
+ allows allowing allowed
9
+ amends amending amended
10
+ bumps bumping bumped
11
+ calculates calculating calculated
12
+ changes changing changed
13
+ cleans cleaning cleaned
14
+ commits committing committed
15
+ corrects correcting corrected
16
+ creates creating created
17
+ darkens darkening darkened
18
+ disables disabling disabled
19
+ displays displaying displayed
20
+ drys drying dryed
21
+ ends ending ended
22
+ enforces enforcing enforced
23
+ enqueues enqueuing enqueued
24
+ extracts extracting extracted
25
+ finishes finishing finished
26
+ fixes fixing fixed
27
+ formats formatting formatted
28
+ guards guarding guarded
29
+ handles handling handled
30
+ hides hiding hid
31
+ increases increasing increased
32
+ ignores ignoring ignored
33
+ implements implementing implemented
34
+ improves improving improved
35
+ keeps keeping kept
36
+ kills killing killed
37
+ makes making made
38
+ merges merging merged
39
+ moves moving moved
40
+ permits permitting permitted
41
+ prevents preventing prevented
42
+ pushes pushing pushed
43
+ rebases rebasing rebased
44
+ refactors refactoring refactored
45
+ removes removing removed
46
+ renames renaming renamed
47
+ reorders reordering reordered
48
+ requires requiring required
49
+ restores restoring restored
50
+ sends sending sent
51
+ sets setting
52
+ separates separating separated
53
+ shows showing showed
54
+ skips skipping skipped
55
+ sorts sorting
56
+ speeds speeding sped
57
+ starts starting started
58
+ supports supporting supported
59
+ takes taking took
60
+ tests testing tested
61
+ truncates truncating truncated
62
+ updates updating updated
63
+ uses using used
64
+ )
65
+
66
+ def validate_line(lineno, text, _branch_name)
67
+ if lineno == 1 && wrong_tense?(text)
68
+ add_error(lineno, "Message must use present imperative tense.")
69
+ end
70
+ end
71
+
72
+ def wrong_tense?(text)
73
+ first_word = text.split.first(2).detect { |w| w =~ /\A\w/ }
74
+ first_word && VERB_BLACKLIST.include?(first_word.downcase)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,14 @@
1
+ require "fit-commit/validators/base"
2
+
3
+ module FitCommit
4
+ module Validators
5
+ class Wip < Base
6
+ def validate_line(lineno, text, branch_name)
7
+ if lineno == 1 && branch_name == "master" &&
8
+ text.split.any? { |word| word == "WIP" }
9
+ add_error(lineno, "Do not commit WIPs to master.")
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module FitCommit
2
+ VERSION = "1.0.1"
3
+ end
data/lib/fit-commit.rb ADDED
@@ -0,0 +1,21 @@
1
+ require "fit-commit/runner"
2
+
3
+ module FitCommit
4
+ def self.run
5
+ runner.run || exit(1)
6
+ end
7
+
8
+ private
9
+
10
+ def self.runner
11
+ FitCommit::Runner.new(message_path, branch_name)
12
+ end
13
+
14
+ def self.message_path
15
+ ENV.fetch("COMMIT_MESSAGE_PATH")
16
+ end
17
+
18
+ def self.branch_name
19
+ `git branch | grep '^\*' | cut -b3-`.strip
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env sh
2
+ #
3
+ # This hook will attempt to setup your environment before running checks.
4
+
5
+ if which rvm >/dev/null 2>/dev/null
6
+ then cmd="rvm default do ruby"
7
+ elif which rbenv >/dev/null 2>/dev/null
8
+ then cmd="rbenv exec ruby"
9
+ else cmd="ruby"
10
+ fi
11
+
12
+ export COMMIT_MESSAGE_PATH=$1
13
+
14
+ ${cmd} -rrubygems -e '
15
+ begin
16
+ require "fit-commit"
17
+ true
18
+ rescue LoadError => e
19
+ $stderr.puts <<-MESSAGE
20
+ fit-commit: WARNING: Skipping checks because: #{e}
21
+ fit-commit: Did you set your Ruby version?
22
+ MESSAGE
23
+ false
24
+ end and FitCommit.run
25
+ ' < /dev/tty
@@ -0,0 +1,81 @@
1
+ require "minitest/autorun"
2
+ require "fit-commit/runner"
3
+
4
+ describe FitCommit::Runner do
5
+ after do
6
+ commit_msg_file.unlink
7
+ end
8
+
9
+ def call_runner
10
+ allow_commit = runner.run
11
+ stdout.rewind
12
+ allow_commit
13
+ end
14
+
15
+ let(:commit_msg_file) do
16
+ Tempfile.new("test-commit-msg").tap do |f|
17
+ f.write(commit_msg)
18
+ f.close
19
+ end
20
+ end
21
+ let(:stdout) { StringIO.new }
22
+ let(:stdin) { StringIO.new }
23
+ let(:branch_name) { "any" }
24
+ let(:runner) do
25
+ FitCommit::Runner.new(commit_msg_file.path, branch_name, stdout, stdin)
26
+ end
27
+
28
+ describe "empty commit msg" do
29
+ let(:commit_msg) { "" }
30
+ it "returns truthy value without printing to stdout" do
31
+ assert call_runner
32
+ assert stdout.read.empty?
33
+ end
34
+ end
35
+
36
+ describe "commit msg consists of all comments" do
37
+ let(:commit_msg) { "\n#hi\n#yo" }
38
+ it "returns truthy value without printing to stdout" do
39
+ assert call_runner
40
+ assert stdout.read.empty?
41
+ end
42
+ end
43
+
44
+ describe "commit msg is present but no errors" do
45
+ let(:commit_msg) { "hello\n\nhi\n#" }
46
+ it "returns truthy value without printing to stdout" do
47
+ assert call_runner
48
+ assert stdout.read.empty?
49
+ end
50
+ end
51
+
52
+ describe "commit msg contains errors" do
53
+ let(:commit_msg) { "foo.\nbar" }
54
+
55
+ def assert_error_output
56
+ stdout_lines = stdout.read.lines.map(&:chomp)
57
+ assert_equal 7, stdout_lines.size
58
+ assert_equal commit_msg, stdout_lines[0..1].join("\n")
59
+ assert_empty stdout_lines[2]
60
+ assert_match(/\A1: Error: /, stdout_lines[3])
61
+ assert_match(/\A2: Error: /, stdout_lines[4])
62
+ assert_empty stdout_lines[5]
63
+ assert_equal "Force commit? [y/n] ", stdout_lines[6]
64
+ end
65
+
66
+ describe "user does not force commit" do
67
+ let(:stdin) { StringIO.new("n") }
68
+ it "prints errors to stdout and returns falsey value" do
69
+ assert !call_runner
70
+ assert_error_output
71
+ end
72
+ end
73
+ describe "user forces commit" do
74
+ let(:stdin) { StringIO.new("y") }
75
+ it "prints errors to stdout and returns truthy value" do
76
+ assert call_runner
77
+ assert_error_output
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,47 @@
1
+ require "minitest/autorun"
2
+ require "fit-commit/validators/frathouse"
3
+
4
+ describe FitCommit::Validators::Frathouse do
5
+ let(:validator) { FitCommit::Validators::Frathouse.new(commit_lines, branch_name) }
6
+ let(:commit_lines) { FitCommit::Line.from_array(commit_msg.split("\n")) }
7
+
8
+ describe "master branch" do
9
+ let(:branch_name) { "master" }
10
+ describe "contains swear word" do
11
+ let(:commit_msg) { "fucking foobar" }
12
+ it "has error" do
13
+ validator.validate
14
+ assert_equal 1, validator.errors[1].size
15
+ assert_empty validator.warnings
16
+ end
17
+ end
18
+ describe "contains swear words on multiple lines" do
19
+ let(:commit_msg) { "damn\n\nIE7 is fucking bullshit!" }
20
+ it "has 1 error per line" do
21
+ validator.validate
22
+ assert_equal 1, validator.errors[1].size
23
+ assert_equal 1, validator.errors[3].size
24
+ assert_empty validator.warnings
25
+ end
26
+ end
27
+ describe "does not contain swear words" do
28
+ let(:commit_msg) { "foo" }
29
+ it "does not have errors/warnings" do
30
+ validator.validate
31
+ assert_empty validator.errors
32
+ assert_empty validator.warnings
33
+ end
34
+ end
35
+ end
36
+ describe "not master branch" do
37
+ let(:branch_name) { "notmaster" }
38
+ describe "contains swear word" do
39
+ let(:commit_msg) { "fucking foo" }
40
+ it "does not have errors/warnings" do
41
+ validator.validate
42
+ assert_empty validator.errors
43
+ assert_empty validator.warnings
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,107 @@
1
+ require "minitest/autorun"
2
+ require "fit-commit/validators/line_length"
3
+
4
+ describe FitCommit::Validators::LineLength do
5
+ let(:validator) { FitCommit::Validators::LineLength.new(commit_lines, branch_name) }
6
+ let(:commit_lines) { FitCommit::Line.from_array(commit_msg.split("\n")) }
7
+
8
+ let(:branch_name) { "any" }
9
+
10
+ describe "first line" do
11
+ describe "first line is empty" do
12
+ let(:commit_msg) { "\n\nbar" }
13
+ it "has error" do
14
+ validator.validate
15
+ assert_equal 1, validator.errors[1].size
16
+ assert_empty validator.warnings
17
+ end
18
+ end
19
+ describe "first line is not empty" do
20
+ let(:commit_msg) { "foo\n\nbar" }
21
+ it "does not have error" do
22
+ validator.validate
23
+ assert_empty validator.errors
24
+ assert_empty validator.warnings
25
+ end
26
+ end
27
+ describe "first line is over warning limit" do
28
+ let(:commit_msg) do
29
+ "x" * (FitCommit::Validators::LineLength::FIRST_LINE_MAX_LENGTH + 1)
30
+ end
31
+ it "has a warning" do
32
+ validator.validate
33
+ assert_empty validator.errors
34
+ assert_equal 1, validator.warnings[1].size
35
+ end
36
+ end
37
+ describe "first line is over error limit" do
38
+ let(:commit_msg) do
39
+ "x" * (FitCommit::Validators::LineLength::LINE_MAX_LENGTH + 1)
40
+ end
41
+ it "has an error and no warning" do
42
+ validator.validate
43
+ assert_equal 1, validator.errors[1].size
44
+ assert_empty validator.warnings
45
+ end
46
+ end
47
+ end
48
+ describe "second line" do
49
+ describe "second line is not empty" do
50
+ let(:commit_msg) { "foo\nbar" }
51
+ it "has error" do
52
+ validator.validate
53
+ assert_equal 1, validator.errors[2].size
54
+ assert_empty validator.warnings
55
+ end
56
+ end
57
+ describe "second line is not empty and too long" do
58
+ let(:commit_msg) do
59
+ "foo\n" + ("x" * (FitCommit::Validators::LineLength::LINE_MAX_LENGTH + 1))
60
+ end
61
+ it "only mentions blank error" do
62
+ validator.validate
63
+ assert_equal 1, validator.errors[2].size
64
+ assert_match(/must be blank/, validator.errors[2][0])
65
+ assert_empty validator.warnings
66
+ end
67
+ end
68
+ describe "second line is empty" do
69
+ let(:commit_msg) { "foo\n\nbar" }
70
+ it "does not have error" do
71
+ validator.validate
72
+ assert_empty validator.errors
73
+ assert_empty validator.warnings
74
+ end
75
+ end
76
+ describe "does not have a second line" do
77
+ let(:commit_msg) { "foo" }
78
+ it "does not have error" do
79
+ validator.validate
80
+ assert_empty validator.errors
81
+ assert_empty validator.warnings
82
+ end
83
+ end
84
+ end
85
+ describe "body text" do
86
+ describe "line is over length limit" do
87
+ let(:commit_msg) do
88
+ "foo\n\n" + ("x" * (FitCommit::Validators::LineLength::LINE_MAX_LENGTH + 1))
89
+ end
90
+ it "has error" do
91
+ validator.validate
92
+ assert_equal 1, validator.errors[3].size
93
+ assert_empty validator.warnings
94
+ end
95
+ end
96
+ describe "line is equal to length limit" do
97
+ let(:commit_msg) do
98
+ "foo\n\n" + ("x" * FitCommit::Validators::LineLength::LINE_MAX_LENGTH)
99
+ end
100
+ it "does not have error" do
101
+ validator.validate
102
+ assert_empty validator.errors
103
+ assert_empty validator.warnings
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,25 @@
1
+ require "minitest/autorun"
2
+ require "fit-commit/validators/summary_period"
3
+
4
+ describe FitCommit::Validators::SummaryPeriod do
5
+ let(:validator) { FitCommit::Validators::SummaryPeriod.new(commit_lines, branch_name) }
6
+ let(:commit_lines) { FitCommit::Line.from_array(commit_msg.split("\n")) }
7
+ let(:branch_name) { "any" }
8
+
9
+ describe "summary ends with period" do
10
+ let(:commit_msg) { "foo bar." }
11
+ it "has error" do
12
+ validator.validate
13
+ assert_equal 1, validator.errors[1].size
14
+ assert_empty validator.warnings
15
+ end
16
+ end
17
+ describe "summary does not end with period" do
18
+ let(:commit_msg) { "foo bar\n\nhi." }
19
+ it "does not have errors/warnings" do
20
+ validator.validate
21
+ assert_empty validator.errors
22
+ assert_empty validator.warnings
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ require "minitest/autorun"
2
+ require "fit-commit/validators/tense"
3
+
4
+ describe FitCommit::Validators::Tense do
5
+ let(:validator) { FitCommit::Validators::Tense.new(commit_lines, branch_name) }
6
+ let(:commit_lines) { FitCommit::Line.from_array(commit_msg.split("\n")) }
7
+
8
+ let(:branch_name) { "anybranch" }
9
+
10
+ describe "uses incorrect tense on first line" do
11
+ let(:commit_msg) { "Changed something\nhi" }
12
+ it "has error" do
13
+ validator.validate
14
+ assert_equal 1, validator.errors[1].size
15
+ assert_empty validator.warnings
16
+ end
17
+ end
18
+
19
+ describe "uses incorrect tense on a line other than first line" do
20
+ let(:commit_msg) { "hi\nChanged something" }
21
+ it "does not have errors/warnings" do
22
+ validator.validate
23
+ assert_empty validator.errors
24
+ assert_empty validator.warnings
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ require "minitest/autorun"
2
+ require "fit-commit/validators/wip"
3
+
4
+ describe FitCommit::Validators::Wip do
5
+ let(:validator) { FitCommit::Validators::Wip.new(commit_lines, branch_name) }
6
+ let(:commit_lines) { FitCommit::Line.from_array(commit_msg.split("\n")) }
7
+
8
+ describe "master branch" do
9
+ let(:branch_name) { "master" }
10
+ describe "contains WIP" do
11
+ let(:commit_msg) { "WIP foo" }
12
+ it "has error" do
13
+ validator.validate
14
+ assert_equal 1, validator.errors[1].size
15
+ assert_empty validator.warnings
16
+ end
17
+ end
18
+ describe "does not contain WIP" do
19
+ let(:commit_msg) { "foo" }
20
+ it "does not have errors/warnings" do
21
+ validator.validate
22
+ assert_empty validator.errors
23
+ assert_empty validator.warnings
24
+ end
25
+ end
26
+ end
27
+ describe "not master branch" do
28
+ let(:branch_name) { "notmaster" }
29
+ describe "contains WIP" do
30
+ let(:commit_msg) { "WIP foo" }
31
+ it "does not have errors/warnings" do
32
+ validator.validate
33
+ assert_empty validator.errors
34
+ assert_empty validator.warnings
35
+ end
36
+ end
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fit-commit
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Foley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: swearjar
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.4'
55
+ description: A Git hook to validate your commit messages, based largely on Tim Pope's
56
+ authoritative guide.
57
+ email:
58
+ - foley3@gmail.com
59
+ executables:
60
+ - fit-commit
61
+ extensions: []
62
+ extra_rdoc_files:
63
+ - README.md
64
+ files:
65
+ - ".gitignore"
66
+ - Gemfile
67
+ - Gemfile.lock
68
+ - LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - TODO.txt
72
+ - bin/fit-commit
73
+ - fit-commit.gemspec
74
+ - lib/fit-commit.rb
75
+ - lib/fit-commit/cli.rb
76
+ - lib/fit-commit/has_errors.rb
77
+ - lib/fit-commit/installer.rb
78
+ - lib/fit-commit/line.rb
79
+ - lib/fit-commit/runner.rb
80
+ - lib/fit-commit/validators/base.rb
81
+ - lib/fit-commit/validators/frathouse.rb
82
+ - lib/fit-commit/validators/line_length.rb
83
+ - lib/fit-commit/validators/summary_period.rb
84
+ - lib/fit-commit/validators/tense.rb
85
+ - lib/fit-commit/validators/wip.rb
86
+ - lib/fit-commit/version.rb
87
+ - templates/hooks/commit-msg
88
+ - test/runner_test.rb
89
+ - test/validators/frathouse_test.rb
90
+ - test/validators/line_length_test.rb
91
+ - test/validators/summary_period_test.rb
92
+ - test/validators/tense_test.rb
93
+ - test/validators/wip_test.rb
94
+ homepage: https://github.com/m1foley/fit-commit
95
+ licenses:
96
+ - MIT
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options:
100
+ - "--main"
101
+ - README.md
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.2.3
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: A Git hook to validate your commit messages
120
+ test_files:
121
+ - test/runner_test.rb
122
+ - test/validators/frathouse_test.rb
123
+ - test/validators/line_length_test.rb
124
+ - test/validators/summary_period_test.rb
125
+ - test/validators/tense_test.rb
126
+ - test/validators/wip_test.rb
127
+ has_rdoc: