diff --git a/README.md b/README.md index 36126a2c..0c682d8b 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ The `overcommit` executable supports the following command-line flags: Command Line Flag | Description --------------------------|---------------------------------------------------- `-i`/`--install` | Install Overcommit hooks in a repository +`-d`/`--directory` | Install Overcommit hooks in a repository to .d/overcommit. Eg. (.git/hooks/pre-commit.d/overcommit) `-u`/`--uninstall` | Remove Overcommit hooks from a repository `-f`/`--force` | Don't bail on install if other hooks already exist--overwrite them `-l`/`--list-hooks` | Display all available hooks in the current repository diff --git a/lib/overcommit/cli.rb b/lib/overcommit/cli.rb index 9848c646..1cd4c4da 100644 --- a/lib/overcommit/cli.rb +++ b/lib/overcommit/cli.rb @@ -90,6 +90,10 @@ def add_installation_options(opts) @options[:action] = :install end + opts.on('-d', '--directory', 'Use directory format for hooks: .git/hooks/.d/overcommit') do + @options[:directory] = true + end + opts.on('-f', '--force', 'Overwrite any previously installed hooks') do @options[:force] = true end diff --git a/lib/overcommit/installer.rb b/lib/overcommit/installer.rb index 79287b30..b7ac3715 100644 --- a/lib/overcommit/installer.rb +++ b/lib/overcommit/installer.rb @@ -80,6 +80,12 @@ def master_hook_install_path def ensure_directory(path) FileUtils.mkdir_p(path) + + dirs = Overcommit::Utils.supported_hook_types(@options[:directory]). + map{|hook_path| path + '/' + File.dirname(hook_path) }.uniq.compact + dirs.each do |hook_dir| + FileUtils.mkdir_p(hook_dir) + end end def validate_target @@ -110,7 +116,7 @@ def uninstall_master_hook def install_hook_files # Copy each hook type (pre-commit, commit-msg, etc.) from the master hook. Dir.chdir(hooks_path) do - Overcommit::Utils.supported_hook_types.each do |hook_type| + Overcommit::Utils.supported_hook_types(@options[:directory]).each do |hook_type| unless can_replace_file?(hook_type) raise Overcommit::Exceptions::PreExistingHooks, "Hook '#{File.expand_path(hook_type)}' already exists and " \ @@ -132,12 +138,18 @@ def preserve_old_hooks return unless File.directory?(hooks_path) ensure_directory(old_hooks_path) - Overcommit::Utils.supported_hook_types.each do |hook_type| + Overcommit::Utils.supported_hook_types(@options[:directory]).each do |hook_type| hook_file = File.join(hooks_path, hook_type) unless can_replace_file?(hook_file) log.warning "Hook '#{File.expand_path(hook_type)}' already exists and " \ "was not installed by Overcommit. Moving to '#{old_hooks_path}'" - FileUtils.mv(hook_file, old_hooks_path) + if @options[:directory] + hook_dir = File.basename(File.dirname(hook_file)) + dest_dir = old_hooks_path + "/" + hook_dir + "/" + FileUtils.mv(hook_file, dest_dir, force: true) + else + FileUtils.mv(hook_file, old_hooks_path) + end end end # Remove old-hooks directory if empty (i.e. no old hooks were preserved) diff --git a/lib/overcommit/utils.rb b/lib/overcommit/utils.rb index 130046c3..cfa3b3ec 100644 --- a/lib/overcommit/utils.rb +++ b/lib/overcommit/utils.rb @@ -99,11 +99,13 @@ def camel_case(str) end # Returns a list of supported hook types (pre-commit, commit-msg, etc.) - def supported_hook_types - Dir[File.join(HOOK_DIRECTORY, '*')]. + def supported_hook_types(directory=nil) + result = Dir[File.join(HOOK_DIRECTORY, '*')]. select { |file| File.directory?(file) }. reject { |file| File.basename(file) == 'shared' }. map { |file| File.basename(file).tr('_', '-') } + result = result.map { |file| file + ".d/overcommit" } if directory + result end # Returns a list of supported hook classes (PreCommit, CommitMsg, etc.) diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index ec9b0cca..4ff7428b 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.58.0' + VERSION = '0.58.0-miry' end diff --git a/spec/integration/installing_overcommit_spec.rb b/spec/integration/installing_overcommit_spec.rb index 5c8ebe35..e96550df 100644 --- a/spec/integration/installing_overcommit_spec.rb +++ b/spec/integration/installing_overcommit_spec.rb @@ -15,6 +15,22 @@ end end + context 'when to folders' do + around do |example| + repo do + puts `overcommit --install --directory` + example.run + end + end + + it 'leaves the hooks intact' do + Overcommit::Utils.supported_hook_types.each do |hook_type| + hook_file = File.join('.git', 'hooks', hook_type + '.d', 'overcommit') + File.read(hook_file).should include 'OVERCOMMIT' + end + end + end + context 'when template directory points to the Overcommit template directory' do around do |example| repo(template_dir: Overcommit::Installer::TEMPLATE_DIRECTORY) do diff --git a/spec/integration/template_dir_spec.rb b/spec/integration/template_dir_spec.rb index ebcff83c..09fc533a 100644 --- a/spec/integration/template_dir_spec.rb +++ b/spec/integration/template_dir_spec.rb @@ -21,8 +21,9 @@ it 'contains all other hooks as copies of the master hook' do Overcommit::Utils.supported_hook_types.each do |hook_type| - FileUtils.compare_file(File.join(hooks_dir, hook_type), - File.join(hooks_dir, 'overcommit-hook')).should == true + hook_file = File.join(hooks_dir, hook_type) + master_hook_file = File.join(hooks_dir, 'overcommit-hook') + expect(FileUtils.compare_file(hook_file, master_hook_file)).to be_truthy, "#{hook_file} is not equal #{master_hook_file}" end end diff --git a/spec/overcommit/utils_spec.rb b/spec/overcommit/utils_spec.rb index 3be592ff..043b5d2a 100644 --- a/spec/overcommit/utils_spec.rb +++ b/spec/overcommit/utils_spec.rb @@ -122,6 +122,13 @@ # rubocop:disable Metrics/LineLength it { should =~ %w[commit-msg pre-commit post-checkout post-commit post-merge post-rewrite pre-push pre-rebase prepare-commit-msg] } # rubocop:enable Metrics/LineLength + + context 'with directory option' do + subject { described_class.supported_hook_types(true) } + # rubocop:disable Metrics/LineLength + it { should =~ %w[commit-msg.d/overcommit pre-commit.d/overcommit post-checkout.d/overcommit post-commit.d/overcommit post-merge.d/overcommit post-rewrite.d/overcommit pre-push.d/overcommit pre-rebase.d/overcommit prepare-commit-msg.d/overcommit] } + # rubocop:enable Metrics/LineLength + end end describe '.supported_hook_type_classes' do diff --git a/template-dir/hooks/commit-msg b/template-dir/hooks/commit-msg index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/commit-msg +++ b/template-dir/hooks/commit-msg @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/overcommit-hook b/template-dir/hooks/overcommit-hook index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/overcommit-hook +++ b/template-dir/hooks/overcommit-hook @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/post-checkout b/template-dir/hooks/post-checkout index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/post-checkout +++ b/template-dir/hooks/post-checkout @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/post-commit b/template-dir/hooks/post-commit index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/post-commit +++ b/template-dir/hooks/post-commit @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/post-merge b/template-dir/hooks/post-merge index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/post-merge +++ b/template-dir/hooks/post-merge @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/post-rewrite b/template-dir/hooks/post-rewrite index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/post-rewrite +++ b/template-dir/hooks/post-rewrite @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/pre-commit b/template-dir/hooks/pre-commit index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/pre-commit +++ b/template-dir/hooks/pre-commit @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/pre-push b/template-dir/hooks/pre-push index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/pre-push +++ b/template-dir/hooks/pre-push @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/pre-rebase b/template-dir/hooks/pre-rebase index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/pre-rebase +++ b/template-dir/hooks/pre-rebase @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier diff --git a/template-dir/hooks/prepare-commit-msg b/template-dir/hooks/prepare-commit-msg index 197dc198..e8d73d9b 100755 --- a/template-dir/hooks/prepare-commit-msg +++ b/template-dir/hooks/prepare-commit-msg @@ -26,6 +26,14 @@ if hook_type == 'overcommit-hook' exit 64 # EX_USAGE end +# Check if the hook located in .git/hooks/.d/ +parent_dir = File.basename(File.dirname($0)) +if parent_dir != "hooks" + if parent_dir.match?(/.d$/) + hook_type = parent_dir[..-3] + end +end + # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier