gitty 0.1.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.
- data/LICENSE +20 -0
- data/README.textile +21 -0
- data/Rakefile +29 -0
- data/assets/helpers/git-cleanup-branches +151 -0
- data/assets/helpers/git-strip-new-whitespace +30 -0
- data/assets/helpers/git-submodule-helper +262 -0
- data/assets/helpers/git-trash +26 -0
- data/assets/helpers/git-when-introduced +16 -0
- data/assets/helpers/hookd_wrapper +22 -0
- data/assets/hooks/clean-patches +43 -0
- data/assets/hooks/git-post-checkout-submodules +74 -0
- data/assets/hooks/git-prevent-messy-rebase +17 -0
- data/assets/hooks/prevent-nocommit-tags +11 -0
- data/bin/git-hook +4 -0
- data/cucumber.yml +1 -0
- data/lib/ext.rb +16 -0
- data/lib/gitty.rb +55 -0
- data/lib/gitty/commands/add.rb +26 -0
- data/lib/gitty/commands/init.rb +55 -0
- data/lib/gitty/commands/list.rb +67 -0
- data/lib/gitty/commands/manager.rb +50 -0
- data/lib/gitty/commands/publish.rb +34 -0
- data/lib/gitty/commands/remove.rb +17 -0
- data/lib/gitty/commands/shell.rb +32 -0
- data/lib/gitty/helpers.rb +21 -0
- data/lib/gitty/hook.rb +42 -0
- data/lib/gitty/runner.rb +44 -0
- data/lib/string.rb +13 -0
- data/spec/gitty/commands/add_spec.rb +5 -0
- data/spec/gitty_spec.rb +59 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/constants.rb +1 -0
- metadata +90 -0
@@ -0,0 +1,50 @@
|
|
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
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Gitty::Hook::Publish < Gitty::Runner
|
2
|
+
include ::Gitty::Helpers
|
3
|
+
|
4
|
+
def run
|
5
|
+
rev = nil
|
6
|
+
puts "Publishing with message #{options[:message].inspect}"
|
7
|
+
with_env_var("GIT_OBJECT_DIRECTORY", File.join(Dir.pwd, ".git/objects")) do
|
8
|
+
Dir.chdir(".git/hooks/shared") do
|
9
|
+
cmd(*%w[git add . -A])
|
10
|
+
cmd(*%w[git commit -m].push(options[:message]))
|
11
|
+
rev = %x{git rev-parse HEAD}.chomp
|
12
|
+
end
|
13
|
+
end
|
14
|
+
# back on the mother repo...
|
15
|
+
cmd(*%w[git push origin -f].push("#{rev}:refs/heads/--hooks--"))
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
def option_parser
|
20
|
+
@option_parser ||= super.tap do |opts|
|
21
|
+
opts.banner = "Usage: git hook publish [options]"
|
22
|
+
opts.on("-m [message]", "--message [message]", "Message for commit (required)") do |m|
|
23
|
+
options[:message] = m
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_args!
|
29
|
+
super
|
30
|
+
if options[:message].nil?
|
31
|
+
puts option_parser
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
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
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
class Gitty::Hook::Shell < Gitty::Runner
|
3
|
+
include ::Gitty::Helpers
|
4
|
+
|
5
|
+
def run
|
6
|
+
exec "bash --init-file #{create_init_file}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_init_file
|
10
|
+
"/tmp/gitty-shell-init".tap do |filename|
|
11
|
+
File.open(filename, "wb") do |f|
|
12
|
+
f.puts(<<-EOF)
|
13
|
+
pushd $HOME > /dev/null
|
14
|
+
[ -f $HOME/.bashrc ] && . $HOME/.bashrc
|
15
|
+
[ -f $HOME/.bash_profile ] && . $HOME/.bash_profile
|
16
|
+
popd > /dev/null
|
17
|
+
export GIT_OBJECT_DIRECTORY="$(pwd)/.git/objects"
|
18
|
+
|
19
|
+
export PS1="Shared Hooks [$(basename $(pwd))]$ "
|
20
|
+
cd .git/hooks/shared
|
21
|
+
rm "#{filename}"
|
22
|
+
EOF
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def option_parser
|
28
|
+
super.tap do |opts|
|
29
|
+
opts.banner = "Usage: git hook shell"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gitty::Helpers
|
2
|
+
def existing_directory!(dir)
|
3
|
+
FileUtils.mkdir_p(dir)
|
4
|
+
Pathname.new(dir)
|
5
|
+
end
|
6
|
+
|
7
|
+
def file_with_existing_directory!(path)
|
8
|
+
FileUtils.mkdir_p(File.dirname(path))
|
9
|
+
Pathname.new(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_env_var(name, value, &block)
|
13
|
+
previous_value, ENV[name] = ENV[name], value
|
14
|
+
yield
|
15
|
+
ENV[name] = previous_value
|
16
|
+
end
|
17
|
+
|
18
|
+
def cmd(*args)
|
19
|
+
system(*args.flatten)
|
20
|
+
end
|
21
|
+
end
|
data/lib/gitty/hook.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
class Gitty::Hook < Gitty::Runner
|
2
|
+
COMMANDS = %w[
|
3
|
+
init
|
4
|
+
list
|
5
|
+
add
|
6
|
+
remove
|
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::Hook.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
|
data/lib/gitty/runner.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require "optparse"
|
2
|
+
class Gitty::Runner
|
3
|
+
attr_reader :stdout, :stderr, :args
|
4
|
+
|
5
|
+
def initialize(args, stdout = STDOUT, stderr = STDERR)
|
6
|
+
@args, @stdout, @stderr = args, stdout, stderr
|
7
|
+
parse_args!
|
8
|
+
end
|
9
|
+
|
10
|
+
def options
|
11
|
+
@options ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def option_parser
|
19
|
+
@option_parser ||= OptionParser.new do |opts|
|
20
|
+
opts.banner = "Usage: #{$0}"
|
21
|
+
opts.separator "Options:"
|
22
|
+
opts.on('--help', "Show help") do |h|
|
23
|
+
@show_help = opts
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_show_help
|
29
|
+
if @show_help
|
30
|
+
puts @show_help
|
31
|
+
exit(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.run(args, stdout = STDOUT, stderr = STDERR)
|
36
|
+
new(args, stdout, stderr).run
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def parse_args!
|
41
|
+
option_parser.parse!(args)
|
42
|
+
handle_show_help
|
43
|
+
end
|
44
|
+
end
|
data/lib/string.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class String
|
2
|
+
def constantize
|
3
|
+
Object.module_eval("::" + self)
|
4
|
+
end
|
5
|
+
|
6
|
+
def underscore
|
7
|
+
gsub(/(^|\b)[A-Z]/) { |l| l.downcase}.gsub(/[A-Z]/) { |l| "_#{l.downcase}" }.gsub("::", "/")
|
8
|
+
end
|
9
|
+
|
10
|
+
def classify
|
11
|
+
gsub(/^[a-z]/) { |l| l.upcase}.gsub(/_[a-z]/) { |l| l[1..1].upcase}.gsub(/\b[a-z]/) {|l| l.upcase}.gsub("/", "::")
|
12
|
+
end
|
13
|
+
end
|
data/spec/gitty_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Gitty do
|
4
|
+
describe ".asset_file" do
|
5
|
+
it "searches first in the specified $GITTY_ASSETS environment variable" do
|
6
|
+
ENV.stub!(:[]).with("GITTY_ASSETS").and_return("/tmp/assets")
|
7
|
+
File.stub!(:exist?).with("/tmp/assets/helpers/helpful").and_return(true)
|
8
|
+
File.stub!(:exist?).with(ASSETS_PATH + "helpers/helpful").and_return(true)
|
9
|
+
|
10
|
+
Gitty.find_asset("helpers/helpful").should == "/tmp/assets/helpers/helpful"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "searches the core ASSETS_PATH if GITTY_ASSETS is not defined" do
|
14
|
+
ENV.stub!(:[]).with("GITTY_ASSETS").and_return(nil)
|
15
|
+
File.stub!(:exist?).with((ASSETS_PATH + "helpers/helpful").to_s).and_return(true)
|
16
|
+
Gitty.find_asset("helpers/helpful").should == (ASSETS_PATH + "helpers/helpful").to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns nil if none the file is not found" do
|
20
|
+
Gitty.find_asset("willy/wonka").should be_nil
|
21
|
+
end
|
22
|
+
end
|
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
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
BIN_PATH = GITTY_LIB_PATH + "../bin"
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gitty
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Harper
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-21 00:00:00 -07:00
|
13
|
+
default_executable: git-hook
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Unobtrusively extend git
|
17
|
+
email: timcharper@gmail.com
|
18
|
+
executables:
|
19
|
+
- git-hook
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.textile
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README.textile
|
28
|
+
- Rakefile
|
29
|
+
- assets/helpers/git-cleanup-branches
|
30
|
+
- assets/helpers/git-strip-new-whitespace
|
31
|
+
- assets/helpers/git-submodule-helper
|
32
|
+
- assets/helpers/git-trash
|
33
|
+
- assets/helpers/git-when-introduced
|
34
|
+
- assets/helpers/hookd_wrapper
|
35
|
+
- assets/hooks/clean-patches
|
36
|
+
- assets/hooks/git-post-checkout-submodules
|
37
|
+
- assets/hooks/git-prevent-messy-rebase
|
38
|
+
- assets/hooks/prevent-nocommit-tags
|
39
|
+
- bin/git-hook
|
40
|
+
- cucumber.yml
|
41
|
+
- lib/ext.rb
|
42
|
+
- lib/gitty.rb
|
43
|
+
- lib/gitty/commands/add.rb
|
44
|
+
- lib/gitty/commands/init.rb
|
45
|
+
- lib/gitty/commands/list.rb
|
46
|
+
- lib/gitty/commands/manager.rb
|
47
|
+
- lib/gitty/commands/publish.rb
|
48
|
+
- lib/gitty/commands/remove.rb
|
49
|
+
- lib/gitty/commands/shell.rb
|
50
|
+
- lib/gitty/helpers.rb
|
51
|
+
- lib/gitty/hook.rb
|
52
|
+
- lib/gitty/runner.rb
|
53
|
+
- lib/string.rb
|
54
|
+
- spec/gitty/commands/add_spec.rb
|
55
|
+
- spec/gitty_spec.rb
|
56
|
+
- spec/spec_helper.rb
|
57
|
+
- spec/support/constants.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/timcharper/gitty
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --charset=UTF-8
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
requirements: []
|
80
|
+
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.3.5
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: Unobtrusively extend git
|
86
|
+
test_files:
|
87
|
+
- spec/gitty/commands/add_spec.rb
|
88
|
+
- spec/gitty_spec.rb
|
89
|
+
- spec/spec_helper.rb
|
90
|
+
- spec/support/constants.rb
|