captain_hoog 1.1.1 → 2.0.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +40 -18
  4. data/bin/hoog +5 -0
  5. data/captain_hoog.gemspec +4 -2
  6. data/features/init.feature +16 -0
  7. data/features/pull.feature +11 -0
  8. data/features/support/env.rb +4 -3
  9. data/features/support/steps/hooks_steps.rb +46 -13
  10. data/features/support/world.rb +21 -1
  11. data/features/testing.feature +18 -0
  12. data/features/version.feature +3 -3
  13. data/lib/captain_hoog/cli/git.rb +26 -0
  14. data/lib/captain_hoog/cli/hoog.rb +129 -0
  15. data/lib/captain_hoog/cli/pull.rb +14 -0
  16. data/lib/captain_hoog/{templates → cli/templates}/hoogfile.erb +0 -0
  17. data/lib/captain_hoog/{templates → cli/templates}/install.erb +1 -0
  18. data/lib/captain_hoog/cli/treasury.rb +15 -0
  19. data/lib/captain_hoog/cli.rb +9 -0
  20. data/lib/captain_hoog/core_ext/hash.rb +4 -4
  21. data/lib/captain_hoog/dependencies.rb +3 -0
  22. data/lib/captain_hoog/git.rb +2 -7
  23. data/lib/captain_hoog/message.rb +31 -0
  24. data/lib/captain_hoog/pre_git.rb +31 -10
  25. data/lib/captain_hoog/test/sandbox.rb +1 -1
  26. data/lib/captain_hoog/version.rb +1 -1
  27. data/lib/captain_hoog.rb +19 -12
  28. data/spec/fixtures/neverland.git/HEAD +1 -0
  29. data/spec/fixtures/neverland.git/config +6 -0
  30. data/spec/fixtures/neverland.git/description +1 -0
  31. data/spec/fixtures/neverland.git/hooks/applypatch-msg.sample +15 -0
  32. data/spec/fixtures/neverland.git/hooks/commit-msg.sample +24 -0
  33. data/spec/fixtures/neverland.git/hooks/post-update.sample +8 -0
  34. data/spec/fixtures/neverland.git/hooks/pre-applypatch.sample +14 -0
  35. data/spec/fixtures/neverland.git/hooks/pre-commit.sample +49 -0
  36. data/spec/fixtures/neverland.git/hooks/pre-push.sample +53 -0
  37. data/spec/fixtures/neverland.git/hooks/pre-rebase.sample +169 -0
  38. data/spec/fixtures/neverland.git/hooks/pre-receive.sample +24 -0
  39. data/spec/fixtures/neverland.git/hooks/prepare-commit-msg.sample +36 -0
  40. data/spec/fixtures/neverland.git/hooks/update.sample +128 -0
  41. data/spec/fixtures/neverland.git/info/exclude +6 -0
  42. data/spec/fixtures/plugins/test_plugins/divide.rb +4 -0
  43. data/spec/fixtures/plugins/test_plugins/passing/pure/foo/foo.rb +2 -1
  44. data/spec/lib/captain_hoog/git_spec.rb +2 -2
  45. data/spec/lib/captain_hoog/plugin_spec.rb +1 -1
  46. data/spec/lib/captain_hoog/pre_git_spec.rb +36 -19
  47. metadata +75 -11
  48. data/bin/githoog +0 -118
  49. data/lib/captain_hoog/errors.rb +0 -1
@@ -0,0 +1,129 @@
1
+ module CaptainHoog
2
+ module Cli
3
+ autoload :Git, 'captain_hoog/cli/git'
4
+ autoload :Pull, 'captain_hoog/cli/pull'
5
+ class Hoog < Thor
6
+ include Thor::Actions
7
+ include Git
8
+ include Pull
9
+
10
+ def self.exit_on_failure?
11
+ true
12
+ end
13
+
14
+ def self.source_root
15
+ File.join(File.dirname(__FILE__), "templates")
16
+ end
17
+
18
+ def self.hookin_repo
19
+ "git@github.com:RSCSCybersecurity/hookins.git"
20
+ end
21
+
22
+ class_option :type, type: :string, default: 'pre-commit'
23
+ class_option :project_dir, type: :string, default: Dir.getwd
24
+ class_option :plugins_dir, type: :string, default: Dir.getwd
25
+
26
+ map %w[--version -v] => :__print_version
27
+
28
+ option :skip_hookins, type: :boolean, default: false
29
+ option :silence, type: :boolean, default: false
30
+ desc "install","Installs the hook into your Git repository"
31
+ def install(*_args)
32
+ check_if_git_present
33
+ check_if_option_present("plugins_dir")
34
+ init_environment(home_dir: Dir.home,
35
+ silence: options[:silence],
36
+ skip_hookins: options[:skip_hookins])
37
+ install_hook({ as: options[:type],
38
+ context: {
39
+ root_dir: Dir.getwd,
40
+ plugins_dir: options[:plugins_dir],
41
+ project_dir: options[:project_dir]
42
+ }
43
+ })
44
+ puts "Installed hook as #{options[:type]} hook".green
45
+ end
46
+
47
+ desc "remove", "Removes a hook from your Git repository"
48
+ def remove(*_args)
49
+ check_if_git_present
50
+ remove_hook(as: options[:type])
51
+ puts "The #{options[:type]} hook is removed.".green
52
+ end
53
+
54
+ option :from, type: :string, required: true
55
+ option :to, type: :string, required: true
56
+ desc "move", "Moves a hook from type to another"
57
+ def move(*_args)
58
+ check_if_git_present
59
+ if options[:from] == options[:to]
60
+ puts "--from and --to arguments are the same".red
61
+ raise Thor::Error
62
+ else
63
+ move_hook(options)
64
+ puts "The #{options[:from]} hook is moved to #{options[:to]} hook.".green
65
+ end
66
+ end
67
+
68
+ desc "version, -v", "Prints out the version"
69
+ def __print_version
70
+ puts CaptainHoog::VERSION
71
+ end
72
+
73
+ option :home, type: :string
74
+ desc "init", "Initializes the Captain Hoog Environment"
75
+ def init
76
+ home_dir = options[:home]
77
+ init_environment(home_dir: home_dir)
78
+ end
79
+
80
+ desc 'treasury', 'Manages the treasury and holds the hoogs'
81
+ subcommand 'treasury', Treasury
82
+
83
+ private
84
+
85
+ def install_hook(config)
86
+ opts = config[:context]
87
+ opts[:type] = config[:as]
88
+ copy_config_file(opts)
89
+ template("install.erb",File.join(hooks_dir, config[:as]), opts)
90
+ FileUtils.chmod(0755,File.join(hooks_dir, config[:as]))
91
+ end
92
+
93
+ def remove_hook(config)
94
+ FileUtils.rm_rf(File.join(hooks_dir, config[:as]))
95
+ end
96
+
97
+ def move_hook(config)
98
+ from = File.join(hooks_dir, config[:from])
99
+ to = File.join(hooks_dir, config[:to])
100
+ FileUtils.mv(from, to)
101
+ end
102
+
103
+ def check_if_option_present(type)
104
+ unless options.has_key?(type)
105
+ puts "No value provided for required options '--#{type}'".red
106
+ raise Thor::Error
107
+ end
108
+ end
109
+
110
+ def copy_config_file(opts={})
111
+ template('hoogfile.erb', git_dir.join('hoogfile.yml'), opts)
112
+ end
113
+
114
+ def init_environment(home_dir: Dir.home,
115
+ silence: false,
116
+ skip_hookins: false)
117
+ environment_dir = File.join(home_dir, '.hoog')
118
+ treasury_dir = File.join(environment_dir, 'treasury')
119
+ if File.exist?(treasury_dir)
120
+ puts "Treasury already exists. Skipping.".yellow unless silence
121
+ else
122
+ puts "Initializing treasury".green unless silence
123
+ FileUtils.mkdir_p(treasury_dir)
124
+ end
125
+ pull_and_clone(self.class.hookin_repo, treasury_dir) unless skip_hookins
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,14 @@
1
+ module CaptainHoog
2
+ module Cli
3
+ module Pull
4
+ module_function
5
+
6
+ def pull_and_clone(repository_url, path)
7
+ target_name = File.basename(repository_url.split('/').last, '.git')
8
+ ::Git.clone(repository_url, target_name, path: path)
9
+ rescue
10
+ puts "Default hookin treasury already exists. Skipping.".yellow
11
+ end
12
+ end
13
+ end
14
+ end
@@ -9,6 +9,7 @@ CaptainHoog::PreGit.configure do |config|
9
9
  config.plugins_dir = hoog_config.plugins_dir
10
10
  config.project_dir = hoog_config.project_dir
11
11
  config.plugins_conf = hoog_config.plugins_env
12
+ config.context = '<%=config[:type] %>'
12
13
  #config.headline_on_success = "All is fine."
13
14
  #config.headline_on_failure = "Oops. Something went wrong"
14
15
  end
@@ -0,0 +1,15 @@
1
+ module CaptainHoog
2
+ module Cli
3
+ autoload :Pull, 'captain_hoog/cli/pull'
4
+ class Treasury < Thor
5
+ include Pull
6
+
7
+ desc 'pull','Pulls from repository into the treasury'
8
+ option :home, type: :string
9
+ def pull(repository_url)
10
+ path = options[:home] ? options[:home] : CaptainHoog.treasury_path
11
+ pull_and_clone(repository_url, path)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ #require 'captain_hoog/cli/treasury'
2
+ #require 'captain_hoog/cli/hoog'
3
+
4
+ module CaptainHoog
5
+ module Cli
6
+ autoload :Treasury, 'captain_hoog/cli/treasury'
7
+ autoload :Hoog, 'captain_hoog/cli/hoog'
8
+ end
9
+ end
@@ -2,10 +2,10 @@ class Hash
2
2
  def stringify_keys
3
3
  reduce({}) do |hash, (key, value)|
4
4
  new_value = if value.respond_to?(:stringify_keys)
5
- value.stringify_keys
6
- else
7
- value
8
- end
5
+ value.stringify_keys
6
+ else
7
+ value
8
+ end
9
9
  hash.merge(key.to_s => new_value)
10
10
  end
11
11
  end
@@ -3,3 +3,6 @@ require 'terminal-table'
3
3
  require 'yaml'
4
4
  require 'ostruct'
5
5
  require 'erb'
6
+ require 'thor'
7
+ require 'pathname'
8
+ require 'git'
@@ -13,13 +13,8 @@ module CaptainHoog
13
13
  end
14
14
  end
15
15
 
16
- def message
17
- if block_given?
18
- @message = yield
19
- unless @message.is_a?(String)
20
- raise CaptainHoog::Errors::MessageResultNotValidError
21
- end
22
- end
16
+ def message(color: :red, &blk)
17
+ @message = CaptainHoog::Message.new(color, blk) if blk
23
18
  end
24
19
 
25
20
  def helper(name,&block)
@@ -0,0 +1,31 @@
1
+ module CaptainHoog
2
+ class Message
3
+
4
+ def initialize(color, body)
5
+ @body = body
6
+ @color = color
7
+ end
8
+
9
+ def call(no_color: true)
10
+ (no_color || will_have_no_color) ? message : message.send(@color)
11
+ end
12
+
13
+ def message
14
+ message = @body.call
15
+ check_msg(message)
16
+ message
17
+ end
18
+
19
+ private
20
+ def check_msg(msg)
21
+ unless msg.is_a?(String)
22
+ raise CaptainHoog::Errors::MessageResultNotValidError
23
+ end
24
+ end
25
+
26
+ def will_have_no_color
27
+ @color.eql?(:none)
28
+ end
29
+
30
+ end
31
+ end
@@ -1,16 +1,29 @@
1
1
  module CaptainHoog
2
2
  # Public: Entry class for handling a Pre-Something with plugins.
3
3
  class PreGit
4
+ module PluginDirs
5
+ module_function
6
+ def collect(plugins_dir)
7
+ treasury_path = CaptainHoog.treasury_path
8
+ if File.exist?(treasury_path)
9
+ Dir["#{treasury_path}/**"].each_with_object(plugins_dir) do |dir, res|
10
+ res << dir if File.directory?(dir)
11
+ end
12
+ end
13
+ end
14
+ end
4
15
 
5
- class << self
6
- attr_accessor :project_dir,
7
- :plugins_dir,
8
- :headline_on_success,
9
- :headline_on_failure,
10
- :suppress_headline,
11
- :plugins_conf
16
+ %i{ project_dir
17
+ headline_on_success
18
+ headline_on_failure
19
+ suppress_headline
20
+ plugins_conf
21
+ context }.each do |class_method|
22
+ singleton_class.send(:attr_accessor, class_method)
12
23
  end
13
24
 
25
+ singleton_class.send(:attr_reader, :plugins_dir)
26
+
14
27
  # Public: Runs the hook.
15
28
  #
16
29
  # Inits a new instance of self and evaluates the plugins (if found some)
@@ -29,6 +42,12 @@ module CaptainHoog
29
42
  yield(self) if block_given?
30
43
  end
31
44
 
45
+ def self.plugins_dir=(plugins_dir)
46
+ @plugins_dir = []
47
+ PluginDirs.collect(@plugins_dir)
48
+ (@plugins_dir << plugins_dir).flatten!
49
+ end
50
+
32
51
  def initialize(plugins_list = nil)
33
52
  @plugins = []
34
53
  @plugins_list = plugins_list
@@ -69,6 +88,7 @@ module CaptainHoog
69
88
  env = Env.new
70
89
  env[:project_dir] = self.class.project_dir
71
90
  env[:plugins_config] = self.class.plugins_conf
91
+ env[:context ] = self.class.context
72
92
  env
73
93
  end
74
94
 
@@ -78,10 +98,10 @@ module CaptainHoog
78
98
 
79
99
  def message_on_failure
80
100
  unless self.class.suppress_headline
81
- puts defined_message_on(:failure).red
101
+ puts defined_message_on(:failure)
82
102
  puts "\n"
83
103
  @results.select{|result| not result[:result] }.each do |result|
84
- puts result[:message].red
104
+ puts result[:message].call(no_color: false)
85
105
  end
86
106
  end
87
107
  end
@@ -102,7 +122,7 @@ module CaptainHoog
102
122
  end
103
123
 
104
124
  def shared_plugins_dir_present?
105
- File.exists?(shared_plugins_dir)
125
+ File.exist?(shared_plugins_dir)
106
126
  end
107
127
 
108
128
  def shared_plugins_dir
@@ -110,6 +130,7 @@ module CaptainHoog
110
130
  end
111
131
 
112
132
  def read_plugins_from_dir(dir, env)
133
+ return unless dir
113
134
  unless File.basename(dir).match(/test/)
114
135
  Dir["#{dir}/**"].each do |file|
115
136
  if File.directory?(file)
@@ -72,7 +72,7 @@ module CaptainHoog
72
72
  git = eigenplugin.instance_variable_get(:@git)
73
73
  {
74
74
  test: git.instance_variable_get(:@test_result),
75
- message: git.instance_variable_get(:@message)
75
+ message: git.instance_variable_get(:@message).call
76
76
  }
77
77
  end
78
78
  end
@@ -1,3 +1,3 @@
1
1
  module CaptainHoog
2
- VERSION = "1.1.1"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/captain_hoog.rb CHANGED
@@ -1,17 +1,24 @@
1
- require "captain_hoog/version"
2
1
  require "captain_hoog/dependencies"
3
2
  require "captain_hoog/core_ext"
4
- require "captain_hoog/errors"
5
- require "captain_hoog/delegatable"
6
- require "captain_hoog/helper_table"
7
- require "captain_hoog/env"
8
- require "captain_hoog/git"
9
- require "captain_hoog/plugin"
10
- require "captain_hoog/pre_git"
11
- require "captain_hoog/plugin_list"
12
- require "captain_hoog/struct/hoog_struct"
13
- require "captain_hoog/hoogfile"
14
3
 
15
4
  module CaptainHoog
16
- # Your code goes here...
5
+
6
+ autoload :Version, 'captain_hoog/version'
7
+ autoload :Errors, 'captain_hoog/errors/dsl_errors'
8
+ autoload :Delegatable, 'captain_hoog/delegatable'
9
+ autoload :HelperTable, 'captain_hoog/helper_table'
10
+ autoload :Env, 'captain_hoog/env'
11
+ autoload :Git, 'captain_hoog/git'
12
+ autoload :Plugin, 'captain_hoog/plugin'
13
+ autoload :PreGit, 'captain_hoog/pre_git'
14
+ autoload :PluginList, 'captain_hoog/plugin_list'
15
+ autoload :Struct, 'captain_hoog/struct/hoog_struct'
16
+ autoload :Hoogfile, 'captain_hoog/hoogfile'
17
+ autoload :Cli, 'captain_hoog/cli'
18
+ autoload :Message, 'captain_hoog/message'
19
+
20
+ module_function
21
+ def treasury_path
22
+ File.join(Dir.home, '.hoog', 'treasury')
23
+ end
17
24
  end
@@ -0,0 +1 @@
1
+ ref: refs/heads/master
@@ -0,0 +1,6 @@
1
+ [core]
2
+ repositoryformatversion = 0
3
+ filemode = true
4
+ bare = true
5
+ ignorecase = true
6
+ precomposeunicode = true
@@ -0,0 +1 @@
1
+ Unnamed repository; edit this file 'description' to name the repository.
@@ -0,0 +1,15 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to check the commit log message taken by
4
+ # applypatch from an e-mail message.
5
+ #
6
+ # The hook should exit with non-zero status after issuing an
7
+ # appropriate message if it wants to stop the commit. The hook is
8
+ # allowed to edit the commit message file.
9
+ #
10
+ # To enable this hook, rename this file to "applypatch-msg".
11
+
12
+ . git-sh-setup
13
+ commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
14
+ test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
15
+ :
@@ -0,0 +1,24 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to check the commit log message.
4
+ # Called by "git commit" with one argument, the name of the file
5
+ # that has the commit message. The hook should exit with non-zero
6
+ # status after issuing an appropriate message if it wants to stop the
7
+ # commit. The hook is allowed to edit the commit message file.
8
+ #
9
+ # To enable this hook, rename this file to "commit-msg".
10
+
11
+ # Uncomment the below to add a Signed-off-by line to the message.
12
+ # Doing this in a hook is a bad idea in general, but the prepare-commit-msg
13
+ # hook is more suited to it.
14
+ #
15
+ # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
16
+ # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
17
+
18
+ # This example catches duplicate Signed-off-by lines.
19
+
20
+ test "" = "$(grep '^Signed-off-by: ' "$1" |
21
+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
22
+ echo >&2 Duplicate Signed-off-by lines.
23
+ exit 1
24
+ }