gitty 0.3.7 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +40 -0
- data/assets/helpers/hookd_wrapper +1 -11
- data/assets/helpers/update-shared-hooks +22 -0
- data/assets/hooks/auto-submodules +10 -5
- data/lib/gitty/commands/init.rb +19 -4
- data/lib/gitty/commands/install.rb +2 -11
- data/lib/gitty/commands/share.rb +34 -0
- data/lib/gitty/hook.rb +43 -24
- data/lib/gitty/hook_command.rb +1 -0
- data/lib/gitty.rb +4 -0
- data/spec/gitty/hook_spec.rb +15 -0
- metadata +4 -2
data/README.textile
CHANGED
@@ -13,9 +13,49 @@ Missing features:
|
|
13
13
|
|
14
14
|
* Only receive hooks from trusted publishers. (currently when gitty is activated on a repository, any hook published to origin is automatically installed)
|
15
15
|
* It's very young and might break
|
16
|
+
* Remote repository must be named origin for shared hooks to work. This is currently not configurable.
|
16
17
|
|
17
18
|
h2. Documentation
|
18
19
|
|
20
|
+
h3. Initialization
|
21
|
+
|
22
|
+
To use gitty with a git repository, you need to install the basic gitty hooks.
|
23
|
+
|
24
|
+
<pre>
|
25
|
+
git hook init
|
26
|
+
</pre>
|
27
|
+
|
28
|
+
* Any existing hooks will be preserved. They are moved to .git/hooks/local/<hook-name>.d/original
|
29
|
+
|
30
|
+
h3. Enabling sharing
|
31
|
+
|
32
|
+
By default, it's turned off (security reasons). To enable it:
|
33
|
+
|
34
|
+
<pre>
|
35
|
+
git hook init --enable-sharing
|
36
|
+
</pre>
|
37
|
+
|
38
|
+
h3. Adding hooks
|
39
|
+
|
40
|
+
To see available hooks:
|
41
|
+
|
42
|
+
<pre>
|
43
|
+
git hook list
|
44
|
+
</pre>
|
45
|
+
|
46
|
+
To install one:
|
47
|
+
|
48
|
+
<pre>
|
49
|
+
git hook install <hook-name>
|
50
|
+
</pre>
|
51
|
+
|
52
|
+
To share one:
|
53
|
+
|
54
|
+
<pre>
|
55
|
+
git hook share <hook-name>
|
56
|
+
git hook publish -m "added <hook-name>"
|
57
|
+
</pre>
|
58
|
+
|
19
59
|
Read the cucumber features for an idea of how it works and what it does
|
20
60
|
|
21
61
|
h2. Issues
|
@@ -2,17 +2,7 @@
|
|
2
2
|
dirname=$(dirname $0)
|
3
3
|
hooktype=$(basename $0)
|
4
4
|
|
5
|
-
|
6
|
-
remote_branch=$(git show-ref origin/--hooks--)
|
7
|
-
[ -n "$remote_branch" ] && (
|
8
|
-
cd ${dirname}/shared > /dev/null
|
9
|
-
local_rev=$(GIT_OBJECT_DIRECTORY="../../objects" git rev-parse HEAD)
|
10
|
-
[ "${remote_branch%% *}" != "$local_rev" ] && (
|
11
|
-
echo "Hook updates were applied:" 1>&2
|
12
|
-
GIT_OBJECT_DIRECTORY=../../objects git branch origin/--hooks-- ${remote_branch%% *} -f 1>&2
|
13
|
-
GIT_OBJECT_DIRECTORY=../../objects git merge ${remote_branch%% *} 1>&2
|
14
|
-
)
|
15
|
-
)
|
5
|
+
[ -x "$dirname/gitty/update-shared-hooks" ] && . "$dirname/gitty/update-shared-hooks"
|
16
6
|
|
17
7
|
for base_dir in "${dirname}"/{shared,local}; do
|
18
8
|
[ -d "${base_dir}/${hooktype}.d" ] || continue
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Check for updates. Since there is no post-fetch hook, we check before we're about to run a hook.
|
3
|
+
remote_branch=$(git show-ref origin/--hooks--)
|
4
|
+
[ -n "$remote_branch" ] && (
|
5
|
+
cd ${dirname}/shared > /dev/null
|
6
|
+
local_rev=$(GIT_OBJECT_DIRECTORY="../../objects" git rev-parse HEAD)
|
7
|
+
[ "${remote_branch%% *}" != "$local_rev" ] && (
|
8
|
+
echo "Hook updates were applied:" 1>&2
|
9
|
+
GIT_OBJECT_DIRECTORY=../../objects git branch origin/--hooks-- ${remote_branch%% *} -f 1>&2
|
10
|
+
# This is a bit of a hack. If we're in the middle of commit, we need to borrow the index. But don't worry, we'll put it back!
|
11
|
+
if [ -f ../../index.lock ]; then
|
12
|
+
mv ../../index.lock ../../index.lock_ 1>&2
|
13
|
+
mv ../../index ../../index_ 1>&2
|
14
|
+
fi
|
15
|
+
GIT_OBJECT_DIRECTORY=../../objects git reset HEAD 1>&2
|
16
|
+
GIT_OBJECT_DIRECTORY=../../objects git reset --hard origin/--hooks-- 1>&2
|
17
|
+
if [ -f ../../index.lock_ ]; then
|
18
|
+
mv ../../index.lock_ ../../index.lock 1>&2
|
19
|
+
mv ../../index_ ../../index 1>&2
|
20
|
+
fi
|
21
|
+
)
|
22
|
+
)
|
@@ -8,7 +8,7 @@
|
|
8
8
|
# - If a submodule has been removed from the branch you move to, it alerts you
|
9
9
|
# - If a submodule has been added on the branch you move to, it alerts you
|
10
10
|
# - Otherwise, it checks out the revision for you
|
11
|
-
# version: 0.
|
11
|
+
# version: 0.3
|
12
12
|
# targets: ["pre-rebase", "post-applypatch", "post-checkout", "post-merge"]
|
13
13
|
|
14
14
|
# this is a bit of a hack: when a rebase is ran, we don't want to have the initial checkout update submodules
|
@@ -23,6 +23,7 @@ if File.exist?(".git/queue-rebase-run")
|
|
23
23
|
exit 0
|
24
24
|
end
|
25
25
|
|
26
|
+
# Not pretty... but well tested!! Refactor me.
|
26
27
|
module GitMethods
|
27
28
|
def chdir_parent
|
28
29
|
Dir.chdir('..') until File.directory?('.git') || Dir.pwd == '/'
|
@@ -97,12 +98,12 @@ previous_submodules = list_submodules('HEAD@{1}')
|
|
97
98
|
end
|
98
99
|
end
|
99
100
|
if ref.match(/^refs\/heads/)
|
100
|
-
|
101
|
+
output = %x(git checkout '#{File.basename(ref)}' 2>&1)
|
101
102
|
if $? == 0
|
102
|
-
STDERR.puts "
|
103
|
+
STDERR.puts "Switched to branch #{File.basename(ref)}"
|
103
104
|
exit 0
|
104
105
|
else
|
105
|
-
STDERR.puts "Couldn't update submodule
|
106
|
+
STDERR.puts "Couldn't update submodule: #{output}"
|
106
107
|
exit $?
|
107
108
|
end
|
108
109
|
end
|
@@ -114,7 +115,11 @@ previous_submodules = list_submodules('HEAD@{1}')
|
|
114
115
|
divergent_commits=%x{git rev-list #{ref}..#{local_ref}}.strip
|
115
116
|
if divergent_commits.empty?
|
116
117
|
STDERR.puts "fastforwarding #{local_ref} to #{ref}"
|
117
|
-
|
118
|
+
if File.read(".git/HEAD").include?("ref: refs/heads/#{local_ref}")
|
119
|
+
system("git merge #{ref}")
|
120
|
+
else
|
121
|
+
system("git branch -f #{local_ref} #{ref}")
|
122
|
+
end
|
118
123
|
exec("git checkout #{local_ref}")
|
119
124
|
end
|
120
125
|
end
|
data/lib/gitty/commands/init.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
class Gitty::HookCommand::Init < Gitty::Runner
|
3
3
|
include ::Gitty::Helpers
|
4
|
+
include FileUtils
|
4
5
|
|
5
6
|
CLIENT_HOOKS = %w[
|
6
7
|
applypatch-msg
|
@@ -17,12 +18,23 @@ class Gitty::HookCommand::Init < Gitty::Runner
|
|
17
18
|
]
|
18
19
|
def run
|
19
20
|
puts "Initializing with gitty"
|
20
|
-
|
21
|
-
|
21
|
+
# MESSY!
|
22
|
+
mkdir_p(".git/hooks/gitty")
|
23
|
+
mkdir_p(".git/hooks/shared")
|
24
|
+
mkdir_p(".git/hooks/local")
|
25
|
+
cp((ASSETS_PATH + "helpers/hookd_wrapper").to_s, ".git/hooks/gitty/hookd_wrapper")
|
26
|
+
chmod(0755, ".git/hooks/gitty/hookd_wrapper")
|
27
|
+
if options[:sharing]
|
28
|
+
cp((ASSETS_PATH + "helpers/update-shared-hooks").to_s, ".git/hooks/gitty/update-shared-hooks")
|
29
|
+
chmod(0755, ".git/hooks/gitty/update-shared-hooks")
|
30
|
+
end
|
22
31
|
|
23
32
|
CLIENT_HOOKS.each do |hook|
|
24
|
-
|
25
|
-
|
33
|
+
if File.exist?(".git/hooks/#{hook}")
|
34
|
+
mkdir_p(".git/hooks/local/#{hook}.d")
|
35
|
+
mv(".git/hooks/#{hook}", ".git/hooks/local/#{hook}.d/original")
|
36
|
+
end
|
37
|
+
ln_sf("gitty/hookd_wrapper", ".git/hooks/#{hook}")
|
26
38
|
end
|
27
39
|
|
28
40
|
hooks_rev = remote_hooks_rev
|
@@ -43,6 +55,9 @@ class Gitty::HookCommand::Init < Gitty::Runner
|
|
43
55
|
def option_parser
|
44
56
|
super.tap do |opts|
|
45
57
|
opts.banner = "Usage: git hook init"
|
58
|
+
opts.on("-s", "--enable-sharing", "Enable sharing") do
|
59
|
+
options[:sharing] = true
|
60
|
+
end
|
46
61
|
end
|
47
62
|
end
|
48
63
|
|
@@ -11,22 +11,13 @@ class Gitty::HookCommand::Install < Gitty::Runner
|
|
11
11
|
stderr.puts "no hook named '#{@hookname}' found."
|
12
12
|
exit 1
|
13
13
|
end
|
14
|
-
|
15
|
-
hook.
|
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)
|
14
|
+
hook.install(:local)
|
15
|
+
stdout.puts "#hook #{hook.name} has been installed."
|
23
16
|
end
|
24
17
|
|
25
18
|
def option_parser
|
26
19
|
@option_parser ||= super.tap do |opts|
|
27
20
|
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
21
|
end
|
31
22
|
end
|
32
23
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Gitty::HookCommand::Share < 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, :install_kind => :local) || Gitty::Hook.find(@hookname, :installed => false)
|
10
|
+
if hook.nil?
|
11
|
+
stderr.puts "no hook named '#{@hookname}' is available"
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
if hook.install_kind == :shared
|
15
|
+
stderr.puts "hook #{@hookname} is already installed"
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
unless Gitty.sharing_enabled?
|
19
|
+
stderr.puts "WARNING: sharing is disabled on your repository. Run git hook init --enable-sharing to turn it on."
|
20
|
+
end
|
21
|
+
hook.share!
|
22
|
+
stdout.puts "To propagate this change other developers, run 'git hook publish -m \"added #{hook.name}...\""
|
23
|
+
end
|
24
|
+
|
25
|
+
def options
|
26
|
+
@options ||= super.update(:kind => :local)
|
27
|
+
end
|
28
|
+
|
29
|
+
def option_parser
|
30
|
+
@option_parser ||= super.tap do |opts|
|
31
|
+
opts.banner = "Usage: git hook install [opts] hook-name"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/gitty/hook.rb
CHANGED
@@ -100,28 +100,49 @@ class Gitty::Hook
|
|
100
100
|
@meta_data ||= self.class.extract_meta_data(File.read(path))
|
101
101
|
end
|
102
102
|
|
103
|
+
protected
|
104
|
+
def copy_to(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_sf(
|
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 destroy
|
123
|
+
target_hook_path = path
|
124
|
+
base_directory = self.class.installed_path(install_kind)
|
125
|
+
meta_data["targets"].each do |target|
|
126
|
+
targetd_path = base_directory + "#{target}.d"
|
127
|
+
rm_f(targetd_path + name)
|
128
|
+
FileUtils.rmdir(targetd_path) if Dir.glob((targetd_path + "*").to_s).empty?
|
129
|
+
end
|
130
|
+
rm(target_hook_path)
|
131
|
+
# TODO - clean up helpers
|
132
|
+
end
|
133
|
+
|
103
134
|
module AvailableHookStrategy
|
104
135
|
def install(which = :local)
|
105
|
-
|
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_sf(
|
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
|
136
|
+
copy_to(which)
|
120
137
|
end
|
121
138
|
|
122
139
|
def uninstall
|
123
140
|
# do nothing
|
124
141
|
end
|
142
|
+
|
143
|
+
def share!
|
144
|
+
copy_to(:shared)
|
145
|
+
end
|
125
146
|
end
|
126
147
|
|
127
148
|
module InstalledHookStrategy
|
@@ -130,15 +151,13 @@ class Gitty::Hook
|
|
130
151
|
end
|
131
152
|
|
132
153
|
def uninstall
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
rm(target_hook_path)
|
141
|
-
# TODO - clean up helpers
|
154
|
+
destroy
|
155
|
+
end
|
156
|
+
|
157
|
+
def share!
|
158
|
+
return nil if install_kind == :shared
|
159
|
+
copy_to(:shared)
|
160
|
+
destroy
|
142
161
|
end
|
143
162
|
end
|
144
163
|
|
data/lib/gitty/hook_command.rb
CHANGED
data/lib/gitty.rb
CHANGED
data/spec/gitty/hook_spec.rb
CHANGED
@@ -138,4 +138,19 @@ EOF
|
|
138
138
|
File.directory?(".git/hooks/local/post-merge.d").should be_false
|
139
139
|
end
|
140
140
|
end
|
141
|
+
|
142
|
+
describe "#share" do
|
143
|
+
it "copies the hook straight to shared when uninstalled" do
|
144
|
+
hook = Gitty::Hook.find("submodule_updater")
|
145
|
+
hook.share!
|
146
|
+
Gitty::Hook.find("submodule_updater", :install_kind => :shared).should_not be_nil
|
147
|
+
end
|
148
|
+
|
149
|
+
it "copies the hook to shared and uninstalls the :local copy" do
|
150
|
+
hook = installed_hook("submodule_updater")
|
151
|
+
hook.share!
|
152
|
+
Gitty::Hook.find("submodule_updater", :install_kind => :local).should be_nil
|
153
|
+
Gitty::Hook.find("submodule_updater", :install_kind => :shared).should_not be_nil
|
154
|
+
end
|
155
|
+
end
|
141
156
|
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.4.2
|
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-03-
|
12
|
+
date: 2010-03-12 00:00:00 -07:00
|
13
13
|
default_executable: git-hook
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -32,6 +32,7 @@ files:
|
|
32
32
|
- assets/helpers/git-trash
|
33
33
|
- assets/helpers/git-when-introduced
|
34
34
|
- assets/helpers/hookd_wrapper
|
35
|
+
- assets/helpers/update-shared-hooks
|
35
36
|
- assets/hooks/auto-submodules
|
36
37
|
- assets/hooks/clean-patches
|
37
38
|
- assets/hooks/git-prevent-messy-rebase
|
@@ -44,6 +45,7 @@ files:
|
|
44
45
|
- lib/gitty/commands/install.rb
|
45
46
|
- lib/gitty/commands/list.rb
|
46
47
|
- lib/gitty/commands/publish.rb
|
48
|
+
- lib/gitty/commands/share.rb
|
47
49
|
- lib/gitty/commands/shell.rb
|
48
50
|
- lib/gitty/commands/show.rb
|
49
51
|
- lib/gitty/commands/uninstall.rb
|