gitty 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/assets/hooks/{git-post-checkout-submodules → auto-submodules} +28 -2
- data/assets/hooks/{prevent-nocommit-tags → nocommit} +0 -0
- data/bin/git-hook +1 -1
- data/lib/gitty.rb +1 -24
- data/lib/gitty/commands/init.rb +2 -2
- data/lib/gitty/commands/install.rb +32 -0
- data/lib/gitty/commands/list.rb +17 -29
- data/lib/gitty/commands/publish.rb +1 -1
- data/lib/gitty/commands/shell.rb +1 -1
- data/lib/gitty/commands/uninstall.rb +39 -0
- data/lib/gitty/helpers.rb +4 -0
- data/lib/gitty/hook.rb +132 -32
- data/lib/gitty/hook_command.rb +42 -0
- data/spec/gitty/hook_spec.rb +139 -0
- data/spec/gitty_spec.rb +0 -35
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +26 -3
- metadata +10 -9
- data/lib/gitty/commands/add.rb +0 -26
- data/lib/gitty/commands/manager.rb +0 -50
- data/lib/gitty/commands/remove.rb +0 -17
- data/spec/gitty/commands/add_spec.rb +0 -5
@@ -39,6 +39,7 @@ module GitMethods
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
include GitMethods
|
42
|
+
HELPERS = File.expand_path(ENV['HELPERS'], Dir.pwd)
|
42
43
|
|
43
44
|
chdir_parent
|
44
45
|
current_submodules = list_submodules('HEAD')
|
@@ -65,10 +66,35 @@ previous_submodules = list_submodules('HEAD@{1}')
|
|
65
66
|
when rev != current_submodules[path]
|
66
67
|
output_submodule_header(path)
|
67
68
|
# it should be updated to the latest
|
68
|
-
# Fetch if it the change doesn't exist
|
69
69
|
Dir.chdir(path) do
|
70
|
+
# Fetch if it the change doesn't exist
|
70
71
|
system("(git show '#{current_submodules[path]}' 2> /dev/null 1> /dev/null) || git fetch")
|
71
|
-
|
72
|
+
|
73
|
+
current_rev = current_submodules[path]
|
74
|
+
STDERR.puts("submodule is pointing to #{rev}")
|
75
|
+
rev, ref_kind, ref = %x{git for-each-ref}.split("\n").map { |l| l.split(" ") }.detect {|l| l.first == current_rev }
|
76
|
+
|
77
|
+
if ref.nil?
|
78
|
+
STDERR.puts "no known branch is currently at #{current_rev}, so we had to detach your HEAD."
|
79
|
+
STDERR.puts "here are some suggestions: "
|
80
|
+
system("git branch --contains #{current_rev} -a | egrep -v 'no branch|HEAD' 1>&2")
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
if ref.match(/^refs\/heads/)
|
84
|
+
exec("git checkout '#{File.basename(ref)}'")
|
85
|
+
end
|
86
|
+
|
87
|
+
if ref.match(/^refs\/remotes/) then
|
88
|
+
local_ref=File.basename(ref)
|
89
|
+
|
90
|
+
STDERR.puts "Remote branch #{ref} matches"
|
91
|
+
divergent_commits=%x{git rev-list #{ref}..#{local_ref}}.strip
|
92
|
+
if divergent_commits.empty?
|
93
|
+
STDERR.puts "fastforwarding #{local_ref} to #{ref}"
|
94
|
+
system("git branch -f #{local_ref} #{ref}")
|
95
|
+
exec("git checkout #{local_ref}")
|
96
|
+
end
|
97
|
+
end
|
72
98
|
end
|
73
99
|
end
|
74
100
|
end
|
File without changes
|
data/bin/git-hook
CHANGED
data/lib/gitty.rb
CHANGED
@@ -25,31 +25,8 @@ module Gitty
|
|
25
25
|
end
|
26
26
|
nil
|
27
27
|
end
|
28
|
-
|
29
|
-
def self.creating_dir_if_nonexistant(dir)
|
30
|
-
FileUtils.mkdir_p(dir)
|
31
|
-
Pathname.new(dir)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.extract_meta_data(string_or_io)
|
35
|
-
io = string_or_io.respond_to?(:readline) ? string_or_io : StringIO.new(string_or_io)
|
36
|
-
meta_yaml = ""
|
37
|
-
begin
|
38
|
-
while line = io.readline
|
39
|
-
next unless line.match(/^# (description.+)/)
|
40
|
-
meta_yaml = "#{$1}\n"
|
41
|
-
break
|
42
|
-
end
|
43
|
-
|
44
|
-
while line = io.readline
|
45
|
-
break unless line.match(/^# (.+)/)
|
46
|
-
meta_yaml << "#{$1}\n"
|
47
|
-
end
|
48
|
-
rescue EOFError
|
49
|
-
end
|
50
|
-
meta_yaml.empty? ? nil : YAML.load(meta_yaml)
|
51
|
-
end
|
52
28
|
end
|
53
29
|
|
54
30
|
require "gitty/runner.rb"
|
55
31
|
require "gitty/hook.rb"
|
32
|
+
require "gitty/hook_command.rb"
|
data/lib/gitty/commands/init.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
class Gitty::
|
2
|
+
class Gitty::HookCommand::Init < Gitty::Runner
|
3
3
|
include ::Gitty::Helpers
|
4
4
|
|
5
5
|
CLIENT_HOOKS = %w[
|
@@ -34,7 +34,7 @@ class Gitty::Hook::Init < Gitty::Runner
|
|
34
34
|
cmd(*%w[git symbolic-ref HEAD refs/heads/--hooks--])
|
35
35
|
cmd(*%w[git commit --allow-empty -m initial\ commit])
|
36
36
|
end
|
37
|
-
cmd(*%w[git reset --hard]
|
37
|
+
cmd(*%w[git reset --hard] + hooks_rev) if hooks_rev
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Gitty::HookCommand::Install < Gitty::Runner
|
2
|
+
include FileUtils
|
3
|
+
def initialize(args, stdout = STDOUT, stderr = STDERR)
|
4
|
+
super
|
5
|
+
@hookname = args.shift
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
hook = Gitty::Hook.find(@hookname, :installed => false)
|
10
|
+
if hook.nil?
|
11
|
+
stderr.puts "no hook named '#{@hookname}' found."
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
|
15
|
+
hook.install(options[:kind])
|
16
|
+
if options[:kind] == :shared
|
17
|
+
stdout.puts "To propagate this change other developers, run 'git hook publish -m \"added #{hook.name}...\""
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def options
|
22
|
+
@options ||= super.update(:kind => :local)
|
23
|
+
end
|
24
|
+
|
25
|
+
def option_parser
|
26
|
+
@option_parser ||= super.tap do |opts|
|
27
|
+
opts.banner = "Usage: git hook install [opts] hook-name"
|
28
|
+
opts.on("-l", "--local", "Local hook (default)") { |l| options[:kind] = :local }
|
29
|
+
opts.on("-s", "--shared", "Remote hook") { |l| options[:kind] = :shared }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/gitty/commands/list.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
class Gitty::
|
2
|
+
class Gitty::HookCommand::List < Gitty::Runner
|
3
3
|
include ::Gitty::Helpers
|
4
4
|
include FileUtils
|
5
|
-
KINDS = [:local, :shared, :
|
5
|
+
KINDS = [:local, :shared, :uninstalled]
|
6
6
|
|
7
7
|
def run
|
8
8
|
stdout.puts "Listing hooks"
|
@@ -11,17 +11,19 @@ class Gitty::Hook::List < Gitty::Runner
|
|
11
11
|
which_to_show.each { |w| show_hooks(w) }
|
12
12
|
end
|
13
13
|
|
14
|
+
def all_hooks
|
15
|
+
@all_hooks = Gitty::Hook.find_all
|
16
|
+
end
|
17
|
+
|
14
18
|
def show_hooks(which)
|
15
19
|
case which
|
16
|
-
when :local
|
17
|
-
when :
|
18
|
-
when :available then show_available_hooks
|
20
|
+
when :local, :shared then show_local_or_shared_hooks(which)
|
21
|
+
when :uninstalled then show_uninstalled_hooks
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
22
25
|
def show_local_or_shared_hooks(which)
|
23
|
-
hook_names =
|
24
|
-
return if hook_names.empty?
|
26
|
+
hook_names = all_hooks.select { |h| h.install_kind == which.to_sym }.map(&:name)
|
25
27
|
puts "#{which}:\n#{listify(hook_names)}\n\n"
|
26
28
|
end
|
27
29
|
|
@@ -29,25 +31,11 @@ class Gitty::Hook::List < Gitty::Runner
|
|
29
31
|
hooks.map { |h| "- #{h}" }.join("\n")
|
30
32
|
end
|
31
33
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
else
|
38
|
-
[]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def installed_hooks_path(which)
|
43
|
-
Pathname.new(".git/hooks/#{which}/hooks")
|
44
|
-
end
|
45
|
-
|
46
|
-
def show_available_hooks
|
47
|
-
all_hooks = Gitty.asset_paths.map {|asset_path| filenames_in(asset_path + "hooks")}.flatten
|
48
|
-
installed_hooks = [:local, :shared].map { |which| filenames_in(installed_hooks_path(which)) }.flatten
|
49
|
-
available_hooks = all_hooks.sort - installed_hooks.sort
|
50
|
-
puts "available:\n#{listify(available_hooks)}\n\n"
|
34
|
+
def show_uninstalled_hooks
|
35
|
+
available_hook_names = all_hooks.select { |h| ! h.installed? }.map(&:name)
|
36
|
+
installed_hook_names = all_hooks.select { |h| h.installed? }.map(&:name)
|
37
|
+
uninstalled_hooks = (available_hook_names - installed_hook_names).sort
|
38
|
+
puts "uninstalled:\n#{listify(uninstalled_hooks)}\n\n"
|
51
39
|
end
|
52
40
|
|
53
41
|
def option_parser
|
@@ -56,11 +44,11 @@ class Gitty::Hook::List < Gitty::Runner
|
|
56
44
|
opts.on("-l", "--local", "Show local hooks") do
|
57
45
|
options[:local] = true
|
58
46
|
end
|
59
|
-
opts.on("-
|
47
|
+
opts.on("-s", "--shared", "Show shared hooks") do
|
60
48
|
options[:shared] = true
|
61
49
|
end
|
62
|
-
opts.on("-
|
63
|
-
options[:
|
50
|
+
opts.on("-u", "--uninstalled", "Show uninstalled hooks") do
|
51
|
+
options[:uninstalled] = true
|
64
52
|
end
|
65
53
|
end
|
66
54
|
end
|
data/lib/gitty/commands/shell.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
class Gitty::HookCommand::Uninstall < Gitty::Runner
|
2
|
+
include FileUtils
|
3
|
+
def initialize(args, stdout = STDOUT, stderr = STDERR)
|
4
|
+
super
|
5
|
+
@hookname = args.shift
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
options = {:installed => true}
|
10
|
+
options[:install_kind] = options[:kind] if options[:kind]
|
11
|
+
hook = Gitty::Hook.find(@hookname, options)
|
12
|
+
return no_hook_found unless hook
|
13
|
+
hook.uninstall
|
14
|
+
|
15
|
+
stdout.puts "#{hook.install_kind} hook #{hook.name} has been successfully uninstalled."
|
16
|
+
if hook.install_kind == :shared
|
17
|
+
stdout.puts "To propagate this change other developers, run 'git hook publish -m \"removed #{hook.name}\""
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def no_hook_found
|
24
|
+
stderr.puts("there is no installed hook named '#{@hookname}'")
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
def options
|
29
|
+
@options ||= super.update(:kind => :local)
|
30
|
+
end
|
31
|
+
|
32
|
+
def option_parser
|
33
|
+
@option_parser ||= super.tap do |opts|
|
34
|
+
opts.banner = "Usage: git hook uninstall [opts] hook-name"
|
35
|
+
opts.on("-l", "--local", "Local hook (default)") { |l| options[:kind] = :local }
|
36
|
+
opts.on("-s", "--shared", "Remote hook") { |l| options[:kind] = :shared }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/gitty/helpers.rb
CHANGED
data/lib/gitty/hook.rb
CHANGED
@@ -1,42 +1,142 @@
|
|
1
|
-
class Gitty::Hook
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(args, stdout = STDOUT, stderr = STDERR)
|
15
|
-
@args, @stdout, @stderr = args, stdout, stderr
|
16
|
-
if COMMANDS.include?(args.first)
|
17
|
-
@target = Gitty::Hook.const_get(args.shift.classify).new(args, stdout, stderr)
|
1
|
+
class Gitty::Hook
|
2
|
+
include Gitty::Helpers
|
3
|
+
include FileUtils
|
4
|
+
attr_accessor :path
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
options.each do |k,v|
|
8
|
+
send("#{k}=", v)
|
9
|
+
end
|
10
|
+
if installed?
|
11
|
+
extend Gitty::Hook::InstalledHookStrategy
|
18
12
|
else
|
19
|
-
|
13
|
+
extend Gitty::Hook::AvailableHookStrategy
|
20
14
|
end
|
21
15
|
end
|
22
|
-
|
23
|
-
def
|
24
|
-
|
25
|
-
|
16
|
+
|
17
|
+
def self.available_hooks_search_paths
|
18
|
+
Gitty.asset_paths.map { |ap| File.join(ap, "hooks") }
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.installed_hooks_search_paths
|
22
|
+
[installed_hooks_path(:local), installed_hooks_path(:shared)]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.installed_path(which = :local)
|
26
|
+
Pathname.new(".git/hooks/#{which}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.installed_hooks_path(which = :local)
|
30
|
+
installed_path(which) + "hooks"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.installed_helpers_path(which = :local)
|
34
|
+
installed_path(which) + "helpers"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.find_all(filters = {})
|
38
|
+
paths = installed_hooks_search_paths + available_hooks_search_paths
|
39
|
+
candidates = find_all_in_paths(paths)
|
40
|
+
filter_candidates(candidates, filters)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.filter_candidates(candidates, filters = {})
|
44
|
+
filters.each do |field, value|
|
45
|
+
candidates = candidates.select { |c| c.send(field) == value }
|
46
|
+
end
|
47
|
+
candidates
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.find(name, options)
|
51
|
+
find_all(options.merge(:name => name)).first
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.find_all_in_paths(paths)
|
55
|
+
paths.map { |hook_path| Dir.glob(File.join(hook_path, "*")) }.flatten.map do |path|
|
56
|
+
Gitty::Hook.new(:path => path)
|
26
57
|
end
|
27
58
|
end
|
28
59
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
60
|
+
def self.extract_meta_data(string_or_io)
|
61
|
+
io = string_or_io.respond_to?(:readline) ? string_or_io : StringIO.new(string_or_io)
|
62
|
+
meta_yaml = ""
|
63
|
+
begin
|
64
|
+
while line = io.readline
|
65
|
+
next unless line.match(/^# (description.+)/)
|
66
|
+
meta_yaml = "#{$1}\n"
|
67
|
+
break
|
68
|
+
end
|
69
|
+
|
70
|
+
while line = io.readline
|
71
|
+
break unless line.match(/^#()$/) || line.match(/^# (.*?)$/)
|
72
|
+
meta_yaml << "#{$1}\n"
|
73
|
+
end
|
74
|
+
rescue EOFError
|
33
75
|
end
|
34
|
-
|
76
|
+
meta_yaml.empty? ? nil : YAML.load(meta_yaml)
|
35
77
|
end
|
36
78
|
|
37
|
-
def
|
38
|
-
|
39
|
-
opt_p.parse!(args)
|
40
|
-
puts opt_p
|
79
|
+
def installed?
|
80
|
+
install_kind ? true : false
|
41
81
|
end
|
42
|
-
|
82
|
+
alias installed installed?
|
83
|
+
|
84
|
+
def install_kind
|
85
|
+
case
|
86
|
+
when path.include?(self.class.installed_hooks_path(:local).to_s) then :local
|
87
|
+
when path.include?(self.class.installed_hooks_path(:shared).to_s) then :shared
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def name
|
92
|
+
File.basename(path)
|
93
|
+
end
|
94
|
+
|
95
|
+
def <=>(other)
|
96
|
+
path <=> other.path
|
97
|
+
end
|
98
|
+
|
99
|
+
def meta_data
|
100
|
+
@meta_data ||= self.class.extract_meta_data(File.read(path))
|
101
|
+
end
|
102
|
+
|
103
|
+
module AvailableHookStrategy
|
104
|
+
def install(which = :local)
|
105
|
+
target_hook_path = existing_directory!(self.class.installed_hooks_path(which))
|
106
|
+
target_helper_path = existing_directory!(self.class.installed_helpers_path(which))
|
107
|
+
base_directory = self.class.installed_path(which)
|
108
|
+
cp(path, target_hook_path + name)
|
109
|
+
chmod(0755, target_hook_path + name)
|
110
|
+
meta_data["targets"].each do |target|
|
111
|
+
ln_s(
|
112
|
+
"../hooks/#{name}",
|
113
|
+
file_with_existing_directory!(base_directory + "#{target}.d" + name)
|
114
|
+
)
|
115
|
+
end
|
116
|
+
(meta_data["helpers"] || []).each do |helper|
|
117
|
+
cp(Gitty.find_asset("helpers/#{helper}"), target_helper_path + helper)
|
118
|
+
chmod(0755, target_helper_path + helper)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def uninstall
|
123
|
+
# do nothing
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
module InstalledHookStrategy
|
128
|
+
def install(which = :local)
|
129
|
+
# do nothing
|
130
|
+
end
|
131
|
+
|
132
|
+
def uninstall
|
133
|
+
target_hook_path = path
|
134
|
+
base_directory = self.class.installed_path(install_kind)
|
135
|
+
meta_data["targets"].each { |target| rm_f(base_directory + "#{target}.d" + name) }
|
136
|
+
rm(target_hook_path)
|
137
|
+
# TODO - clean up helpers
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
private :path=
|
142
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Gitty::HookCommand < Gitty::Runner
|
2
|
+
COMMANDS = %w[
|
3
|
+
init
|
4
|
+
list
|
5
|
+
install
|
6
|
+
uninstall
|
7
|
+
publish
|
8
|
+
shell
|
9
|
+
]
|
10
|
+
COMMANDS.each do |cmd|
|
11
|
+
autoload cmd.classify.to_sym, (GITTY_PATH + "commands/#{cmd}.rb").to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(args, stdout = STDOUT, stderr = STDERR)
|
15
|
+
@args, @stdout, @stderr = args, stdout, stderr
|
16
|
+
if COMMANDS.include?(args.first)
|
17
|
+
@target = Gitty::HookCommand.const_get(args.shift.classify).new(args, stdout, stderr)
|
18
|
+
else
|
19
|
+
parse_args!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def option_parser
|
24
|
+
@option_parser ||= super.tap do |opts|
|
25
|
+
opts.banner = "Usage: git hook [command]\nCommands are: #{COMMANDS.join(', ')}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
unless File.directory?(".git")
|
31
|
+
stderr.puts "You must run git hook from the root of a git repository"
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
@target && @target.run
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_args!
|
38
|
+
opt_p = option_parser
|
39
|
+
opt_p.parse!(args)
|
40
|
+
puts opt_p
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Gitty::Hook do
|
4
|
+
def installed_hook(name, which = :local)
|
5
|
+
hook = Gitty::Hook.find(name, :installed => false)
|
6
|
+
hook.install(which)
|
7
|
+
Gitty::Hook.find(name, :installed => true)
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
Gitty::Hook.stub!(:available_hooks_search_paths).and_return([SandboxWorld::GITTY_ASSETS + "hooks"])
|
12
|
+
create_file(SandboxWorld::GITTY_ASSETS + "hooks/submodule_updater", <<-EOF)
|
13
|
+
#!/bin/bash
|
14
|
+
# description: managers submodule updating for you
|
15
|
+
# targets: ["post-checkout", "post-merge"]
|
16
|
+
...
|
17
|
+
EOF
|
18
|
+
create_file(SandboxWorld::GITTY_ASSETS + "hooks/no_messy_whitespace", <<-EOF)
|
19
|
+
#!/bin/bash
|
20
|
+
# description: prevents you from committing messy whitespace
|
21
|
+
# targets: ["pre-commit"]
|
22
|
+
...
|
23
|
+
EOF
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".extract_meta_data" do
|
27
|
+
it "extracts meta data from a stream" do
|
28
|
+
stream = <<-EOF
|
29
|
+
#!/usr/bash
|
30
|
+
|
31
|
+
# description: |-
|
32
|
+
# hi
|
33
|
+
#
|
34
|
+
# bye
|
35
|
+
# targets: ["post-merge", "post-checkout"]
|
36
|
+
#
|
37
|
+
|
38
|
+
here's my hook
|
39
|
+
EOF
|
40
|
+
Gitty::Hook.extract_meta_data(stream).should == {
|
41
|
+
"description" => "hi\n\nbye",
|
42
|
+
"targets" => ["post-merge", "post-checkout"]
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns nil when no data found" do
|
47
|
+
stream = <<-EOF
|
48
|
+
#!/usr/bash
|
49
|
+
#
|
50
|
+
#
|
51
|
+
EOF
|
52
|
+
Gitty::Hook.extract_meta_data(stream).should == nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns the data when there's no actual content" do
|
56
|
+
stream = <<-EOF
|
57
|
+
#!/usr/bash
|
58
|
+
#
|
59
|
+
# description: hi
|
60
|
+
EOF
|
61
|
+
Gitty::Hook.extract_meta_data(stream).should == {"description" => "hi"}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
describe ".find_all" do
|
65
|
+
it "returns all available hooks" do
|
66
|
+
Gitty::Hook.find_all(:installed => false).map(&:name).should == %w[no_messy_whitespace submodule_updater]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe ".find" do
|
71
|
+
it "returns an available hook by name" do
|
72
|
+
Gitty::Hook.find("submodule_updater", :installed => false).name.should == "submodule_updater"
|
73
|
+
Gitty::Hook.find("no_messy_whitespace", :installed => false).name.should == "no_messy_whitespace"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "finds installed hooks" do
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#installed?" do
|
81
|
+
it "returns false if the hook is not installed" do
|
82
|
+
Gitty::Hook.find("submodule_updater", :installed => false).installed?.should be_false
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns true if the hook is installed" do
|
86
|
+
Gitty::Hook.find("submodule_updater", :installed => false).install(:local)
|
87
|
+
Gitty::Hook.find("submodule_updater", :installed => true).installed?.should == true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#install_kind" do
|
92
|
+
it "returns :local for local hooks" do
|
93
|
+
installed_hook("submodule_updater", :local).install_kind.should == :local
|
94
|
+
end
|
95
|
+
|
96
|
+
it "returns :shared for shared hooks" do
|
97
|
+
installed_hook("submodule_updater", :shared).install_kind.should == :shared
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#meta_data" do
|
102
|
+
it "reads the meta_data of a given file" do
|
103
|
+
Gitty::Hook.find("submodule_updater", :installed => false).meta_data
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#install" do
|
108
|
+
it "copies an available hook to the install path and links it into the targets" do
|
109
|
+
@hook = Gitty::Hook.find("submodule_updater", :installed => false)
|
110
|
+
@hook.install
|
111
|
+
File.exist?(".git/hooks/local/hooks/submodule_updater").should be_true
|
112
|
+
File.executable?(".git/hooks/local/hooks/submodule_updater").should be_true
|
113
|
+
File.exist?(".git/hooks/local/post-checkout.d/submodule_updater").should be_true
|
114
|
+
File.exist?(".git/hooks/local/post-merge.d/submodule_updater").should be_true
|
115
|
+
end
|
116
|
+
|
117
|
+
it "installs a hook into shared" do
|
118
|
+
@hook = Gitty::Hook.find("submodule_updater", :installed => false)
|
119
|
+
@hook.install(:shared)
|
120
|
+
File.exist?(".git/hooks/shared/hooks/submodule_updater").should be_true
|
121
|
+
File.executable?(".git/hooks/shared/hooks/submodule_updater").should be_true
|
122
|
+
File.exist?(".git/hooks/shared/post-checkout.d/submodule_updater").should be_true
|
123
|
+
File.exist?(".git/hooks/shared/post-merge.d/submodule_updater").should be_true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#uninstall" do
|
128
|
+
it "removes a hook from installed path" do
|
129
|
+
hook = installed_hook("submodule_updater")
|
130
|
+
File.exist?(".git/hooks/local/hooks/submodule_updater").should be_true
|
131
|
+
File.symlink?(".git/hooks/local/post-checkout.d/submodule_updater").should be_true
|
132
|
+
File.symlink?(".git/hooks/local/post-merge.d/submodule_updater").should be_true
|
133
|
+
hook.uninstall
|
134
|
+
File.exist?(".git/hooks/local/hooks/submodule_updater").should be_false
|
135
|
+
File.symlink?(".git/hooks/local/post-checkout.d/submodule_updater").should be_false
|
136
|
+
File.symlink?(".git/hooks/local/post-merge.d/submodule_updater").should be_false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/spec/gitty_spec.rb
CHANGED
@@ -21,39 +21,4 @@ describe Gitty do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
describe ".extract_meta_data" do
|
25
|
-
it "extracts meta data from a stream" do
|
26
|
-
stream = <<-EOF
|
27
|
-
#!/usr/bash
|
28
|
-
|
29
|
-
# description: hi
|
30
|
-
# targets: ["post-merge", "post-checkout"]
|
31
|
-
#
|
32
|
-
|
33
|
-
here's my hook
|
34
|
-
EOF
|
35
|
-
Gitty.extract_meta_data(stream).should == {
|
36
|
-
"description" => "hi",
|
37
|
-
"targets" => ["post-merge", "post-checkout"]
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
it "returns nil when no data found" do
|
42
|
-
stream = <<-EOF
|
43
|
-
#!/usr/bash
|
44
|
-
#
|
45
|
-
#
|
46
|
-
EOF
|
47
|
-
Gitty.extract_meta_data(stream).should == nil
|
48
|
-
end
|
49
|
-
|
50
|
-
it "returns the data when there's no actual content" do
|
51
|
-
stream = <<-EOF
|
52
|
-
#!/usr/bash
|
53
|
-
#
|
54
|
-
# description: hi
|
55
|
-
EOF
|
56
|
-
Gitty.extract_meta_data(stream).should == {"description" => "hi"}
|
57
|
-
end
|
58
|
-
end
|
59
24
|
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,29 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../lib/gitty"
|
2
|
-
SPEC_PATH = GITTY_ROOT_PATH + "spec"
|
3
2
|
require 'rubygems'
|
4
|
-
require
|
3
|
+
require "spec"
|
4
|
+
SPEC_PATH = Pathname.new(File.dirname(__FILE__))
|
5
|
+
require SPEC_PATH + "../features/support/sandbox_world.rb"
|
5
6
|
require SPEC_PATH + "support/constants.rb"
|
6
|
-
|
7
|
+
|
8
|
+
|
9
|
+
require 'forwardable'
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
extend Forwardable
|
12
|
+
def sandbox
|
13
|
+
@sandbox ||= SandboxWorld.new
|
14
|
+
end
|
15
|
+
|
16
|
+
[:run, :in_dir, :current_dir, :create_file, :last_exit_status, :last_stderr, :last_stdout, :reset_sandbox!].each do |m|
|
17
|
+
eval "def #{m}(*args) sandbox.send(:#{m}, *args) end"
|
18
|
+
end
|
19
|
+
|
20
|
+
config.before(:each) do
|
21
|
+
reset_sandbox!
|
22
|
+
@_original_dir = Dir.pwd
|
23
|
+
Dir.chdir(current_dir)
|
24
|
+
end
|
25
|
+
|
26
|
+
config.after(:each) do
|
27
|
+
Dir.chdir(@_original_dir)
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Harper
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-24 00:00:00 -08:00
|
13
13
|
default_executable: git-hook
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -32,27 +32,28 @@ files:
|
|
32
32
|
- assets/helpers/git-trash
|
33
33
|
- assets/helpers/git-when-introduced
|
34
34
|
- assets/helpers/hookd_wrapper
|
35
|
+
- assets/hooks/auto-submodules
|
35
36
|
- assets/hooks/clean-patches
|
36
|
-
- assets/hooks/git-post-checkout-submodules
|
37
37
|
- assets/hooks/git-prevent-messy-rebase
|
38
|
-
- assets/hooks/
|
38
|
+
- assets/hooks/nocommit
|
39
39
|
- bin/git-hook
|
40
40
|
- cucumber.yml
|
41
41
|
- lib/ext.rb
|
42
42
|
- lib/gitty.rb
|
43
|
-
- lib/gitty/commands/add.rb
|
44
43
|
- lib/gitty/commands/init.rb
|
44
|
+
- lib/gitty/commands/install.rb
|
45
45
|
- lib/gitty/commands/list.rb
|
46
|
-
- lib/gitty/commands/manager.rb
|
47
46
|
- lib/gitty/commands/publish.rb
|
48
|
-
- lib/gitty/commands/remove.rb
|
49
47
|
- lib/gitty/commands/shell.rb
|
48
|
+
- lib/gitty/commands/uninstall.rb
|
50
49
|
- lib/gitty/helpers.rb
|
51
50
|
- lib/gitty/hook.rb
|
51
|
+
- lib/gitty/hook_command.rb
|
52
52
|
- lib/gitty/runner.rb
|
53
53
|
- lib/string.rb
|
54
|
-
- spec/gitty/
|
54
|
+
- spec/gitty/hook_spec.rb
|
55
55
|
- spec/gitty_spec.rb
|
56
|
+
- spec/spec.opts
|
56
57
|
- spec/spec_helper.rb
|
57
58
|
- spec/support/constants.rb
|
58
59
|
has_rdoc: true
|
@@ -84,7 +85,7 @@ signing_key:
|
|
84
85
|
specification_version: 3
|
85
86
|
summary: Unobtrusively extend git
|
86
87
|
test_files:
|
87
|
-
- spec/gitty/
|
88
|
+
- spec/gitty/hook_spec.rb
|
88
89
|
- spec/gitty_spec.rb
|
89
90
|
- spec/spec_helper.rb
|
90
91
|
- spec/support/constants.rb
|
data/lib/gitty/commands/add.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require GITTY_PATH + "commands/manager"
|
2
|
-
|
3
|
-
class Gitty::Hook::Add < Gitty::Hook::Manager
|
4
|
-
include FileUtils
|
5
|
-
|
6
|
-
def run
|
7
|
-
cp(src_hook_file, master_hook_file)
|
8
|
-
chmod(0755, master_hook_file)
|
9
|
-
meta_data["targets"].each do |target|
|
10
|
-
ln_s(
|
11
|
-
"../hooks/#{@hookname}",
|
12
|
-
file_with_existing_directory!(base_directory + "#{target}.d" + @hookname)
|
13
|
-
)
|
14
|
-
end
|
15
|
-
(meta_data["helpers"] || []).each do |helper|
|
16
|
-
cp(Gitty.find_asset("helpers/#{helper}"), helpers_directory + helper)
|
17
|
-
chmod(0755, helpers_directory + helper)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def option_parser
|
22
|
-
@option_parser ||= super.tap do |opts|
|
23
|
-
opts.banner = "Usage: git hook add [opts] hook-name"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
class Gitty::Hook::Manager < Gitty::Runner
|
2
|
-
include ::Gitty::Helpers
|
3
|
-
def initialize(args, stdout = STDOUT, stderr = STDERR)
|
4
|
-
super
|
5
|
-
@hookname = args.shift
|
6
|
-
end
|
7
|
-
|
8
|
-
def options
|
9
|
-
@options ||= super.update(:kind => :local)
|
10
|
-
end
|
11
|
-
|
12
|
-
def src_hook_file
|
13
|
-
Gitty.find_asset("hooks/#{@hookname}")
|
14
|
-
end
|
15
|
-
|
16
|
-
def master_hook_file
|
17
|
-
@master_hook_file ||= hooks_directory + @hookname
|
18
|
-
end
|
19
|
-
|
20
|
-
def meta_data
|
21
|
-
@meta_data ||= Gitty.extract_meta_data(File.read(src_hook_file))
|
22
|
-
end
|
23
|
-
|
24
|
-
def run
|
25
|
-
raise NotImplementedError
|
26
|
-
end
|
27
|
-
|
28
|
-
def target_file(hook)
|
29
|
-
@target_file ||= file_with_existing_directory!(base_directory + "#{hook}.d/#{@hookname}")
|
30
|
-
end
|
31
|
-
|
32
|
-
def base_directory
|
33
|
-
@base_directory ||= existing_directory!(".git/hooks/#{options[:kind]}")
|
34
|
-
end
|
35
|
-
|
36
|
-
def helpers_directory
|
37
|
-
@helpers_directory ||= existing_directory!(".git/hooks/#{options[:kind]}/helpers")
|
38
|
-
end
|
39
|
-
|
40
|
-
def hooks_directory
|
41
|
-
existing_directory!(base_directory + "hooks")
|
42
|
-
end
|
43
|
-
|
44
|
-
def option_parser
|
45
|
-
@option_parser ||= super.tap do |opts|
|
46
|
-
opts.on("-l", "--local", "Local hook (default)") { |l| options[:kind] = :local }
|
47
|
-
opts.on("-s", "--shared", "Remote hook") { |l| options[:kind] = :shared }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require GITTY_PATH + "commands/manager"
|
2
|
-
class Gitty::Hook::Remove < Gitty::Hook::Manager
|
3
|
-
include FileUtils
|
4
|
-
def run
|
5
|
-
rm(master_hook_file)
|
6
|
-
meta_data["targets"].each do |target|
|
7
|
-
rm(target_file(target))
|
8
|
-
end
|
9
|
-
# TODO - cleanup helpers
|
10
|
-
end
|
11
|
-
|
12
|
-
def option_parser
|
13
|
-
@option_parser ||= super.tap do |opts|
|
14
|
-
opts.banner = "Usage: git hook remove [opts] hook-name"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|