From 2ce66511090ad4518fce1c20413c93fcfd00339a Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 18:50:37 -0400 Subject: [PATCH 01/13] Add SubmoduleStatus post-checkout hook --- config/default.yml | 6 ++ .../hook/post_checkout/submodule_status.rb | 55 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 lib/overcommit/hook/post_checkout/submodule_status.rb diff --git a/config/default.yml b/config/default.yml index 9c808f68..7e1528de 100644 --- a/config/default.yml +++ b/config/default.yml @@ -430,6 +430,12 @@ PostCheckout: description: 'Generating tags file from source' required_executable: 'ctags' + SubmoduleStatus: + enabled: false + description: 'Checking submodule status' + required_executable: 'git' + flags: ['submodule', 'status'] + # Hooks that run after a commit is created. PostCommit: ALL: diff --git a/lib/overcommit/hook/post_checkout/submodule_status.rb b/lib/overcommit/hook/post_checkout/submodule_status.rb new file mode 100644 index 00000000..8dcec8f3 --- /dev/null +++ b/lib/overcommit/hook/post_checkout/submodule_status.rb @@ -0,0 +1,55 @@ +module Overcommit::Hook::PostCheckout + # Checks the status of submodules in the current repository and + # notifies the user if any are uninitialized, out of date with + # the current index, or contain merge conflicts. + class SubmoduleStatus < Base + SUBMODULE_STATUS_REGEX = / + ^\s*(?[-+U]?)(?\w+) + \s(?[^\s]+?) + (?:\s\((?.+)\))?$ + /x + + SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do + def uninitialized? + prefix == '-' + end + + def outdated? + prefix == '+' + end + + def merge_conflict? + prefix == 'U' + end + end + + def run + result = execute(command) + submodule_statuses = parse_submodule_statuses(result.stdout) + + messages = [] + submodule_statuses.each do |submodule_status| + path = submodule_status.path + if submodule_status.uninitialized? + messages << "Submodule #{path} is uninitialized." + elsif submodule_status.outdated? + messages << "Submodule #{path} is out of date with the current index." + elsif submodule_status.merge_conflict? + messages << "Submodule #{path} has merge conflicts." + end + end + + return :pass if messages.empty? + + [:warn, messages.join("\n")] + end + + private + + def parse_submodule_statuses(output) + output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| + SubmoduleStatus.new(prefix, sha1, path, describe) + end + end + end +end From 8c84f7a50cf158938fcd6f2429d8732315c53e55 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 19:15:36 -0400 Subject: [PATCH 02/13] Add SubmoduleStatus post-commit hook --- config/default.yml | 6 ++ .../hook/post_commit/submodule_status.rb | 55 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 lib/overcommit/hook/post_commit/submodule_status.rb diff --git a/config/default.yml b/config/default.yml index 7e1528de..e1f6bcbd 100644 --- a/config/default.yml +++ b/config/default.yml @@ -456,6 +456,12 @@ PostCommit: description: 'Generating tags file from source' required_executable: 'ctags' + SubmoduleStatus: + enabled: false + description: 'Checking submodule status' + required_executable: 'git' + flags: ['submodule', 'status'] + # Hooks that run after `git merge` executes successfully (no merge conflicts). PostMerge: ALL: diff --git a/lib/overcommit/hook/post_commit/submodule_status.rb b/lib/overcommit/hook/post_commit/submodule_status.rb new file mode 100644 index 00000000..b398bd05 --- /dev/null +++ b/lib/overcommit/hook/post_commit/submodule_status.rb @@ -0,0 +1,55 @@ +module Overcommit::Hook::PostCommit + # Checks the status of submodules in the current repository and + # notifies the user if any are uninitialized, out of date with + # the current index, or contain merge conflicts. + class SubmoduleStatus < Base + SUBMODULE_STATUS_REGEX = / + ^\s*(?[-+U]?)(?\w+) + \s(?[^\s]+?) + (?:\s\((?.+)\))?$ + /x + + SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do + def uninitialized? + prefix == '-' + end + + def outdated? + prefix == '+' + end + + def merge_conflict? + prefix == 'U' + end + end + + def run + result = execute(command) + submodule_statuses = parse_submodule_statuses(result.stdout) + + messages = [] + submodule_statuses.each do |submodule_status| + path = submodule_status.path + if submodule_status.uninitialized? + messages << "Submodule #{path} is uninitialized." + elsif submodule_status.outdated? + messages << "Submodule #{path} is out of date with the current index." + elsif submodule_status.merge_conflict? + messages << "Submodule #{path} has merge conflicts." + end + end + + return :pass if messages.empty? + + [:warn, messages.join("\n")] + end + + private + + def parse_submodule_statuses(output) + output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| + SubmoduleStatus.new(prefix, sha1, path, describe) + end + end + end +end From 7048892d7264065b5456de7adecc10bfc40a9617 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 19:16:04 -0400 Subject: [PATCH 03/13] Add SubmoduleStatus post-merge hook --- config/default.yml | 6 ++ .../hook/post_merge/submodule_status.rb | 55 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 lib/overcommit/hook/post_merge/submodule_status.rb diff --git a/config/default.yml b/config/default.yml index e1f6bcbd..4e466520 100644 --- a/config/default.yml +++ b/config/default.yml @@ -473,6 +473,12 @@ PostMerge: description: 'Generating tags file from source' required_executable: 'ctags' + SubmoduleStatus: + enabled: false + description: 'Checking submodule status' + required_executable: 'git' + flags: ['submodule', 'status'] + # Hooks that run after a commit is modified by an amend or rebase. PostRewrite: ALL: diff --git a/lib/overcommit/hook/post_merge/submodule_status.rb b/lib/overcommit/hook/post_merge/submodule_status.rb new file mode 100644 index 00000000..617cee0f --- /dev/null +++ b/lib/overcommit/hook/post_merge/submodule_status.rb @@ -0,0 +1,55 @@ +module Overcommit::Hook::PostMerge + # Checks the status of submodules in the current repository and + # notifies the user if any are uninitialized, out of date with + # the current index, or contain merge conflicts. + class SubmoduleStatus < Base + SUBMODULE_STATUS_REGEX = / + ^\s*(?[-+U]?)(?\w+) + \s(?[^\s]+?) + (?:\s\((?.+)\))?$ + /x + + SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do + def uninitialized? + prefix == '-' + end + + def outdated? + prefix == '+' + end + + def merge_conflict? + prefix == 'U' + end + end + + def run + result = execute(command) + submodule_statuses = parse_submodule_statuses(result.stdout) + + messages = [] + submodule_statuses.each do |submodule_status| + path = submodule_status.path + if submodule_status.uninitialized? + messages << "Submodule #{path} is uninitialized." + elsif submodule_status.outdated? + messages << "Submodule #{path} is out of date with the current index." + elsif submodule_status.merge_conflict? + messages << "Submodule #{path} has merge conflicts." + end + end + + return :pass if messages.empty? + + [:warn, messages.join("\n")] + end + + private + + def parse_submodule_statuses(output) + output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| + SubmoduleStatus.new(prefix, sha1, path, describe) + end + end + end +end From d82d114b55d4d6bca596346a106e646ff643c5dd Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 19:16:23 -0400 Subject: [PATCH 04/13] Add SubmoduleStatus post-rewrite hook --- config/default.yml | 6 ++ .../hook/post_rewrite/submodule_status.rb | 55 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 lib/overcommit/hook/post_rewrite/submodule_status.rb diff --git a/config/default.yml b/config/default.yml index 4e466520..faf22df0 100644 --- a/config/default.yml +++ b/config/default.yml @@ -490,6 +490,12 @@ PostRewrite: description: 'Generating tags file from source' required_executable: 'ctags' + SubmoduleStatus: + enabled: false + description: 'Checking submodule status' + required_executable: 'git' + flags: ['submodule', 'status'] + # Hooks that run during `git push`, after remote refs have been updated but # before any objects have been transferred. PrePush: diff --git a/lib/overcommit/hook/post_rewrite/submodule_status.rb b/lib/overcommit/hook/post_rewrite/submodule_status.rb new file mode 100644 index 00000000..5209964a --- /dev/null +++ b/lib/overcommit/hook/post_rewrite/submodule_status.rb @@ -0,0 +1,55 @@ +module Overcommit::Hook::PostRewrite + # Checks the status of submodules in the current repository and + # notifies the user if any are uninitialized, out of date with + # the current index, or contain merge conflicts. + class SubmoduleStatus < Base + SUBMODULE_STATUS_REGEX = / + ^\s*(?[-+U]?)(?\w+) + \s(?[^\s]+?) + (?:\s\((?.+)\))?$ + /x + + SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do + def uninitialized? + prefix == '-' + end + + def outdated? + prefix == '+' + end + + def merge_conflict? + prefix == 'U' + end + end + + def run + result = execute(command) + submodule_statuses = parse_submodule_statuses(result.stdout) + + messages = [] + submodule_statuses.each do |submodule_status| + path = submodule_status.path + if submodule_status.uninitialized? + messages << "Submodule #{path} is uninitialized." + elsif submodule_status.outdated? + messages << "Submodule #{path} is out of date with the current index." + elsif submodule_status.merge_conflict? + messages << "Submodule #{path} has merge conflicts." + end + end + + return :pass if messages.empty? + + [:warn, messages.join("\n")] + end + + private + + def parse_submodule_statuses(output) + output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| + SubmoduleStatus.new(prefix, sha1, path, describe) + end + end + end +end From 10d0b2825e0eaf2236b44b330ddee4b153ee2d25 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 19:35:59 -0400 Subject: [PATCH 05/13] Add specs for SubmoduleStatus post-checkout hook --- .../post_checkout/submodule_status_spec.rb | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 spec/overcommit/hook/post_checkout/submodule_status_spec.rb diff --git a/spec/overcommit/hook/post_checkout/submodule_status_spec.rb b/spec/overcommit/hook/post_checkout/submodule_status_spec.rb new file mode 100644 index 00000000..d364843f --- /dev/null +++ b/spec/overcommit/hook/post_checkout/submodule_status_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Overcommit::Hook::PostCheckout::SubmoduleStatus do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + let(:result) { double('result') } + + before do + result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") + subject.stub(:execute).and_return(result) + end + + context 'when submodule is up to date' do + let(:prefix) { '' } + + it { should pass } + end + + context 'when submodule is uninitialized' do + let(:prefix) { '-' } + + it { should warn(/uninitialized/) } + end + + context 'when submodule is outdated' do + let(:prefix) { '+' } + + it { should warn(/out of date/) } + end + + context 'when submodule has merge conflicts' do + let(:prefix) { 'U' } + + it { should warn(/merge conflicts/) } + end +end From de263fa1e37e89207c597bc75d1847e88bb65ada Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 19:36:11 -0400 Subject: [PATCH 06/13] Add specs for SubmoduleStatus post-commit hook --- .../hook/post_commit/submodule_status_spec.rb | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 spec/overcommit/hook/post_commit/submodule_status_spec.rb diff --git a/spec/overcommit/hook/post_commit/submodule_status_spec.rb b/spec/overcommit/hook/post_commit/submodule_status_spec.rb new file mode 100644 index 00000000..a65d127f --- /dev/null +++ b/spec/overcommit/hook/post_commit/submodule_status_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Overcommit::Hook::PostCommit::SubmoduleStatus do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + let(:result) { double('result') } + + before do + result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") + subject.stub(:execute).and_return(result) + end + + context 'when submodule is up to date' do + let(:prefix) { '' } + + it { should pass } + end + + context 'when submodule is uninitialized' do + let(:prefix) { '-' } + + it { should warn(/uninitialized/) } + end + + context 'when submodule is outdated' do + let(:prefix) { '+' } + + it { should warn(/out of date/) } + end + + context 'when submodule has merge conflicts' do + let(:prefix) { 'U' } + + it { should warn(/merge conflicts/) } + end +end From cf8991772c6f5370b3189fe1acd73048922f02fe Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 19:36:24 -0400 Subject: [PATCH 07/13] Add specs for SubmoduleStatus post-merge hook --- .../hook/post_merge/submodule_status_spec.rb | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 spec/overcommit/hook/post_merge/submodule_status_spec.rb diff --git a/spec/overcommit/hook/post_merge/submodule_status_spec.rb b/spec/overcommit/hook/post_merge/submodule_status_spec.rb new file mode 100644 index 00000000..aa6d47f7 --- /dev/null +++ b/spec/overcommit/hook/post_merge/submodule_status_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Overcommit::Hook::PostMerge::SubmoduleStatus do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + let(:result) { double('result') } + + before do + result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") + subject.stub(:execute).and_return(result) + end + + context 'when submodule is up to date' do + let(:prefix) { '' } + + it { should pass } + end + + context 'when submodule is uninitialized' do + let(:prefix) { '-' } + + it { should warn(/uninitialized/) } + end + + context 'when submodule is outdated' do + let(:prefix) { '+' } + + it { should warn(/out of date/) } + end + + context 'when submodule has merge conflicts' do + let(:prefix) { 'U' } + + it { should warn(/merge conflicts/) } + end +end From 8319ca50c2ee3e256a79e343bbd30a3851d4d97e Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Mon, 6 Apr 2015 19:36:44 -0400 Subject: [PATCH 08/13] Add specs for SubmoduleStatus post-rewrite hook --- .../post_rewrite/submodule_status_spec.rb | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 spec/overcommit/hook/post_rewrite/submodule_status_spec.rb diff --git a/spec/overcommit/hook/post_rewrite/submodule_status_spec.rb b/spec/overcommit/hook/post_rewrite/submodule_status_spec.rb new file mode 100644 index 00000000..151f53d0 --- /dev/null +++ b/spec/overcommit/hook/post_rewrite/submodule_status_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Overcommit::Hook::PostRewrite::SubmoduleStatus do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + let(:result) { double('result') } + + before do + result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") + subject.stub(:execute).and_return(result) + end + + context 'when submodule is up to date' do + let(:prefix) { '' } + + it { should pass } + end + + context 'when submodule is uninitialized' do + let(:prefix) { '-' } + + it { should warn(/uninitialized/) } + end + + context 'when submodule is outdated' do + let(:prefix) { '+' } + + it { should warn(/out of date/) } + end + + context 'when submodule has merge conflicts' do + let(:prefix) { 'U' } + + it { should warn(/merge conflicts/) } + end +end From 4b4e01fb1449a729ccc8d9c61862e46bf9e45301 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Tue, 7 Apr 2015 02:35:05 -0400 Subject: [PATCH 09/13] Add SubmoduleStatus struct, regex and helpers to GitRepo --- lib/overcommit/git_repo.rb | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lib/overcommit/git_repo.rb b/lib/overcommit/git_repo.rb index eb2e7e95..524cd7cc 100644 --- a/lib/overcommit/git_repo.rb +++ b/lib/overcommit/git_repo.rb @@ -11,6 +11,50 @@ module GitRepo \s@@.*$ /x + # Regular expression used to extract information from lines of + # `git submodule status` output + SUBMODULE_STATUS_REGEX = / + ^\s*(?[-+U]?)(?\w+) + \s(?[^\s]+?) + (?:\s\((?.+)\))?$ + /x + + # Struct encapsulating submodule information extracted from the + # output of `git submodule status` + SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do + # Returns whether the submodule has not been initialized + def uninitialized? + prefix == '-' + end + + # Returns whether the submodule is out of date with the current + # index, i.e. its checked-out commit differs from that stored in + # the index of the parent repo + def outdated? + prefix == '+' + end + + # Returns whether the submodule reference has a merge conflict + def merge_conflict? + prefix == 'U' + end + end + + # Returns a list of SubmoduleStatus objects, one for each submodule in the + # parent repository. + # + # @option options [Boolean] recursive check submodules recursively + # @return [Array] + def submodule_statuses(options = {}) + flags = '--recursive' if options[:recursive] + + `git submodule status #{flags}`. + scan(SUBMODULE_STATUS_REGEX). + map do |prefix, sha1, path, describe| + SubmoduleStatus.new(prefix, sha1, path, describe) + end + end + # Extract the set of modified lines from a given file. # # @param file_path [String] From 125e816333ec63a0003c8a59d4497cbf88d35f70 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Tue, 7 Apr 2015 02:35:47 -0400 Subject: [PATCH 10/13] Use GitRepo#submodule_statuses in SubmoduleStatus hooks --- .../hook/post_checkout/submodule_status.rb | 29 ++----------------- .../hook/post_commit/submodule_status.rb | 29 ++----------------- .../hook/post_merge/submodule_status.rb | 29 ++----------------- .../hook/post_rewrite/submodule_status.rb | 29 ++----------------- 4 files changed, 8 insertions(+), 108 deletions(-) diff --git a/lib/overcommit/hook/post_checkout/submodule_status.rb b/lib/overcommit/hook/post_checkout/submodule_status.rb index 8dcec8f3..54648216 100644 --- a/lib/overcommit/hook/post_checkout/submodule_status.rb +++ b/lib/overcommit/hook/post_checkout/submodule_status.rb @@ -3,30 +3,7 @@ module Overcommit::Hook::PostCheckout # notifies the user if any are uninitialized, out of date with # the current index, or contain merge conflicts. class SubmoduleStatus < Base - SUBMODULE_STATUS_REGEX = / - ^\s*(?[-+U]?)(?\w+) - \s(?[^\s]+?) - (?:\s\((?.+)\))?$ - /x - - SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do - def uninitialized? - prefix == '-' - end - - def outdated? - prefix == '+' - end - - def merge_conflict? - prefix == 'U' - end - end - def run - result = execute(command) - submodule_statuses = parse_submodule_statuses(result.stdout) - messages = [] submodule_statuses.each do |submodule_status| path = submodule_status.path @@ -46,10 +23,8 @@ def run private - def parse_submodule_statuses(output) - output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| - SubmoduleStatus.new(prefix, sha1, path, describe) - end + def submodule_statuses + Overcommit::GitRepo.submodule_statuses(recursive: config['recursive']) end end end diff --git a/lib/overcommit/hook/post_commit/submodule_status.rb b/lib/overcommit/hook/post_commit/submodule_status.rb index b398bd05..1648768a 100644 --- a/lib/overcommit/hook/post_commit/submodule_status.rb +++ b/lib/overcommit/hook/post_commit/submodule_status.rb @@ -3,30 +3,7 @@ module Overcommit::Hook::PostCommit # notifies the user if any are uninitialized, out of date with # the current index, or contain merge conflicts. class SubmoduleStatus < Base - SUBMODULE_STATUS_REGEX = / - ^\s*(?[-+U]?)(?\w+) - \s(?[^\s]+?) - (?:\s\((?.+)\))?$ - /x - - SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do - def uninitialized? - prefix == '-' - end - - def outdated? - prefix == '+' - end - - def merge_conflict? - prefix == 'U' - end - end - def run - result = execute(command) - submodule_statuses = parse_submodule_statuses(result.stdout) - messages = [] submodule_statuses.each do |submodule_status| path = submodule_status.path @@ -46,10 +23,8 @@ def run private - def parse_submodule_statuses(output) - output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| - SubmoduleStatus.new(prefix, sha1, path, describe) - end + def submodule_statuses + Overcommit::GitRepo.submodule_statuses(recursive: config['recursive']) end end end diff --git a/lib/overcommit/hook/post_merge/submodule_status.rb b/lib/overcommit/hook/post_merge/submodule_status.rb index 617cee0f..979327ff 100644 --- a/lib/overcommit/hook/post_merge/submodule_status.rb +++ b/lib/overcommit/hook/post_merge/submodule_status.rb @@ -3,30 +3,7 @@ module Overcommit::Hook::PostMerge # notifies the user if any are uninitialized, out of date with # the current index, or contain merge conflicts. class SubmoduleStatus < Base - SUBMODULE_STATUS_REGEX = / - ^\s*(?[-+U]?)(?\w+) - \s(?[^\s]+?) - (?:\s\((?.+)\))?$ - /x - - SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do - def uninitialized? - prefix == '-' - end - - def outdated? - prefix == '+' - end - - def merge_conflict? - prefix == 'U' - end - end - def run - result = execute(command) - submodule_statuses = parse_submodule_statuses(result.stdout) - messages = [] submodule_statuses.each do |submodule_status| path = submodule_status.path @@ -46,10 +23,8 @@ def run private - def parse_submodule_statuses(output) - output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| - SubmoduleStatus.new(prefix, sha1, path, describe) - end + def submodule_statuses + Overcommit::GitRepo.submodule_statuses(recursive: config['recursive']) end end end diff --git a/lib/overcommit/hook/post_rewrite/submodule_status.rb b/lib/overcommit/hook/post_rewrite/submodule_status.rb index 5209964a..8e79a16f 100644 --- a/lib/overcommit/hook/post_rewrite/submodule_status.rb +++ b/lib/overcommit/hook/post_rewrite/submodule_status.rb @@ -3,30 +3,7 @@ module Overcommit::Hook::PostRewrite # notifies the user if any are uninitialized, out of date with # the current index, or contain merge conflicts. class SubmoduleStatus < Base - SUBMODULE_STATUS_REGEX = / - ^\s*(?[-+U]?)(?\w+) - \s(?[^\s]+?) - (?:\s\((?.+)\))?$ - /x - - SubmoduleStatus = Struct.new(:prefix, :sha1, :path, :describe) do - def uninitialized? - prefix == '-' - end - - def outdated? - prefix == '+' - end - - def merge_conflict? - prefix == 'U' - end - end - def run - result = execute(command) - submodule_statuses = parse_submodule_statuses(result.stdout) - messages = [] submodule_statuses.each do |submodule_status| path = submodule_status.path @@ -46,10 +23,8 @@ def run private - def parse_submodule_statuses(output) - output.scan(SUBMODULE_STATUS_REGEX).map do |prefix, sha1, path, describe| - SubmoduleStatus.new(prefix, sha1, path, describe) - end + def submodule_statuses + Overcommit::GitRepo.submodule_statuses(recursive: config['recursive']) end end end From a46e01a35d6fe84420f89afb40d95252fb5aba44 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Tue, 7 Apr 2015 02:44:00 -0400 Subject: [PATCH 11/13] Make 'recursive' a config option for SubmoduleStatus --- config/default.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/config/default.yml b/config/default.yml index faf22df0..6773f903 100644 --- a/config/default.yml +++ b/config/default.yml @@ -433,8 +433,7 @@ PostCheckout: SubmoduleStatus: enabled: false description: 'Checking submodule status' - required_executable: 'git' - flags: ['submodule', 'status'] + recursive: false # Hooks that run after a commit is created. PostCommit: @@ -459,8 +458,7 @@ PostCommit: SubmoduleStatus: enabled: false description: 'Checking submodule status' - required_executable: 'git' - flags: ['submodule', 'status'] + recursive: false # Hooks that run after `git merge` executes successfully (no merge conflicts). PostMerge: @@ -476,8 +474,7 @@ PostMerge: SubmoduleStatus: enabled: false description: 'Checking submodule status' - required_executable: 'git' - flags: ['submodule', 'status'] + recursive: false # Hooks that run after a commit is modified by an amend or rebase. PostRewrite: @@ -493,8 +490,7 @@ PostRewrite: SubmoduleStatus: enabled: false description: 'Checking submodule status' - required_executable: 'git' - flags: ['submodule', 'status'] + recursive: false # Hooks that run during `git push`, after remote refs have been updated but # before any objects have been transferred. From 1e3b0a88de1bb54dae3ab24f0ac8dea2f423de76 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Tue, 7 Apr 2015 02:44:47 -0400 Subject: [PATCH 12/13] Update specs with changes to SubmoduleStatus hooks --- .../post_checkout/submodule_status_spec.rb | 30 ++++++++++++++----- .../hook/post_commit/submodule_status_spec.rb | 30 ++++++++++++++----- .../hook/post_merge/submodule_status_spec.rb | 30 ++++++++++++++----- .../post_rewrite/submodule_status_spec.rb | 30 ++++++++++++++----- 4 files changed, 92 insertions(+), 28 deletions(-) diff --git a/spec/overcommit/hook/post_checkout/submodule_status_spec.rb b/spec/overcommit/hook/post_checkout/submodule_status_spec.rb index d364843f..45078f46 100644 --- a/spec/overcommit/hook/post_checkout/submodule_status_spec.rb +++ b/spec/overcommit/hook/post_checkout/submodule_status_spec.rb @@ -5,33 +5,49 @@ let(:context) { double('context') } subject { described_class.new(config, context) } - let(:result) { double('result') } + let(:submodule_status) { double('submodule_status') } before do - result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") - subject.stub(:execute).and_return(result) + submodule_status.stub(:path).and_return('sub') + subject.stub(:submodule_statuses).and_return([submodule_status]) end context 'when submodule is up to date' do - let(:prefix) { '' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: false) + end it { should pass } end context 'when submodule is uninitialized' do - let(:prefix) { '-' } + before do + submodule_status.stub(uninitialized?: true, + outdated?: false, + merge_conflict?: false) + end it { should warn(/uninitialized/) } end context 'when submodule is outdated' do - let(:prefix) { '+' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: true, + merge_conflict?: false) + end it { should warn(/out of date/) } end context 'when submodule has merge conflicts' do - let(:prefix) { 'U' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: true) + end it { should warn(/merge conflicts/) } end diff --git a/spec/overcommit/hook/post_commit/submodule_status_spec.rb b/spec/overcommit/hook/post_commit/submodule_status_spec.rb index a65d127f..2c12d5fe 100644 --- a/spec/overcommit/hook/post_commit/submodule_status_spec.rb +++ b/spec/overcommit/hook/post_commit/submodule_status_spec.rb @@ -5,33 +5,49 @@ let(:context) { double('context') } subject { described_class.new(config, context) } - let(:result) { double('result') } + let(:submodule_status) { double('submodule_status') } before do - result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") - subject.stub(:execute).and_return(result) + submodule_status.stub(:path).and_return('sub') + subject.stub(:submodule_statuses).and_return([submodule_status]) end context 'when submodule is up to date' do - let(:prefix) { '' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: false) + end it { should pass } end context 'when submodule is uninitialized' do - let(:prefix) { '-' } + before do + submodule_status.stub(uninitialized?: true, + outdated?: false, + merge_conflict?: false) + end it { should warn(/uninitialized/) } end context 'when submodule is outdated' do - let(:prefix) { '+' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: true, + merge_conflict?: false) + end it { should warn(/out of date/) } end context 'when submodule has merge conflicts' do - let(:prefix) { 'U' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: true) + end it { should warn(/merge conflicts/) } end diff --git a/spec/overcommit/hook/post_merge/submodule_status_spec.rb b/spec/overcommit/hook/post_merge/submodule_status_spec.rb index aa6d47f7..245fe6c1 100644 --- a/spec/overcommit/hook/post_merge/submodule_status_spec.rb +++ b/spec/overcommit/hook/post_merge/submodule_status_spec.rb @@ -5,33 +5,49 @@ let(:context) { double('context') } subject { described_class.new(config, context) } - let(:result) { double('result') } + let(:submodule_status) { double('submodule_status') } before do - result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") - subject.stub(:execute).and_return(result) + submodule_status.stub(:path).and_return('sub') + subject.stub(:submodule_statuses).and_return([submodule_status]) end context 'when submodule is up to date' do - let(:prefix) { '' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: false) + end it { should pass } end context 'when submodule is uninitialized' do - let(:prefix) { '-' } + before do + submodule_status.stub(uninitialized?: true, + outdated?: false, + merge_conflict?: false) + end it { should warn(/uninitialized/) } end context 'when submodule is outdated' do - let(:prefix) { '+' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: true, + merge_conflict?: false) + end it { should warn(/out of date/) } end context 'when submodule has merge conflicts' do - let(:prefix) { 'U' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: true) + end it { should warn(/merge conflicts/) } end diff --git a/spec/overcommit/hook/post_rewrite/submodule_status_spec.rb b/spec/overcommit/hook/post_rewrite/submodule_status_spec.rb index 151f53d0..c783c029 100644 --- a/spec/overcommit/hook/post_rewrite/submodule_status_spec.rb +++ b/spec/overcommit/hook/post_rewrite/submodule_status_spec.rb @@ -5,33 +5,49 @@ let(:context) { double('context') } subject { described_class.new(config, context) } - let(:result) { double('result') } + let(:submodule_status) { double('submodule_status') } before do - result.stub(:stdout).and_return("#{prefix}#{random_hash} sub (heads/master)") - subject.stub(:execute).and_return(result) + submodule_status.stub(:path).and_return('sub') + subject.stub(:submodule_statuses).and_return([submodule_status]) end context 'when submodule is up to date' do - let(:prefix) { '' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: false) + end it { should pass } end context 'when submodule is uninitialized' do - let(:prefix) { '-' } + before do + submodule_status.stub(uninitialized?: true, + outdated?: false, + merge_conflict?: false) + end it { should warn(/uninitialized/) } end context 'when submodule is outdated' do - let(:prefix) { '+' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: true, + merge_conflict?: false) + end it { should warn(/out of date/) } end context 'when submodule has merge conflicts' do - let(:prefix) { 'U' } + before do + submodule_status.stub(uninitialized?: false, + outdated?: false, + merge_conflict?: true) + end it { should warn(/merge conflicts/) } end From a3b6ab0c2ad724dd003b44629f86b92715481a83 Mon Sep 17 00:00:00 2001 From: Josh Hagins Date: Tue, 7 Apr 2015 02:47:10 -0400 Subject: [PATCH 13/13] Run SubmoduleStatus hooks silently --- config/default.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/default.yml b/config/default.yml index 6773f903..1e502d40 100644 --- a/config/default.yml +++ b/config/default.yml @@ -433,6 +433,7 @@ PostCheckout: SubmoduleStatus: enabled: false description: 'Checking submodule status' + quiet: true recursive: false # Hooks that run after a commit is created. @@ -458,6 +459,7 @@ PostCommit: SubmoduleStatus: enabled: false description: 'Checking submodule status' + quiet: true recursive: false # Hooks that run after `git merge` executes successfully (no merge conflicts). @@ -474,6 +476,7 @@ PostMerge: SubmoduleStatus: enabled: false description: 'Checking submodule status' + quiet: true recursive: false # Hooks that run after a commit is modified by an amend or rebase. @@ -490,6 +493,7 @@ PostRewrite: SubmoduleStatus: enabled: false description: 'Checking submodule status' + quiet: true recursive: false # Hooks that run during `git push`, after remote refs have been updated but