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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +40 -18
- data/bin/hoog +5 -0
- data/captain_hoog.gemspec +4 -2
- data/features/init.feature +16 -0
- data/features/pull.feature +11 -0
- data/features/support/env.rb +4 -3
- data/features/support/steps/hooks_steps.rb +46 -13
- data/features/support/world.rb +21 -1
- data/features/testing.feature +18 -0
- data/features/version.feature +3 -3
- data/lib/captain_hoog/cli/git.rb +26 -0
- data/lib/captain_hoog/cli/hoog.rb +129 -0
- data/lib/captain_hoog/cli/pull.rb +14 -0
- data/lib/captain_hoog/{templates → cli/templates}/hoogfile.erb +0 -0
- data/lib/captain_hoog/{templates → cli/templates}/install.erb +1 -0
- data/lib/captain_hoog/cli/treasury.rb +15 -0
- data/lib/captain_hoog/cli.rb +9 -0
- data/lib/captain_hoog/core_ext/hash.rb +4 -4
- data/lib/captain_hoog/dependencies.rb +3 -0
- data/lib/captain_hoog/git.rb +2 -7
- data/lib/captain_hoog/message.rb +31 -0
- data/lib/captain_hoog/pre_git.rb +31 -10
- data/lib/captain_hoog/test/sandbox.rb +1 -1
- data/lib/captain_hoog/version.rb +1 -1
- data/lib/captain_hoog.rb +19 -12
- data/spec/fixtures/neverland.git/HEAD +1 -0
- data/spec/fixtures/neverland.git/config +6 -0
- data/spec/fixtures/neverland.git/description +1 -0
- data/spec/fixtures/neverland.git/hooks/applypatch-msg.sample +15 -0
- data/spec/fixtures/neverland.git/hooks/commit-msg.sample +24 -0
- data/spec/fixtures/neverland.git/hooks/post-update.sample +8 -0
- data/spec/fixtures/neverland.git/hooks/pre-applypatch.sample +14 -0
- data/spec/fixtures/neverland.git/hooks/pre-commit.sample +49 -0
- data/spec/fixtures/neverland.git/hooks/pre-push.sample +53 -0
- data/spec/fixtures/neverland.git/hooks/pre-rebase.sample +169 -0
- data/spec/fixtures/neverland.git/hooks/pre-receive.sample +24 -0
- data/spec/fixtures/neverland.git/hooks/prepare-commit-msg.sample +36 -0
- data/spec/fixtures/neverland.git/hooks/update.sample +128 -0
- data/spec/fixtures/neverland.git/info/exclude +6 -0
- data/spec/fixtures/plugins/test_plugins/divide.rb +4 -0
- data/spec/fixtures/plugins/test_plugins/passing/pure/foo/foo.rb +2 -1
- data/spec/lib/captain_hoog/git_spec.rb +2 -2
- data/spec/lib/captain_hoog/plugin_spec.rb +1 -1
- data/spec/lib/captain_hoog/pre_git_spec.rb +36 -19
- metadata +75 -11
- data/bin/githoog +0 -118
- 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
|
File without changes
|
@@ -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
|
@@ -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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
data/lib/captain_hoog/git.rb
CHANGED
@@ -13,13 +13,8 @@ module CaptainHoog
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def message
|
17
|
-
if
|
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
|
data/lib/captain_hoog/pre_git.rb
CHANGED
@@ -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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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)
|
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].
|
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.
|
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)
|
data/lib/captain_hoog/version.rb
CHANGED
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
|
-
|
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 @@
|
|
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
|
+
}
|