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 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
- # Check for updates. Since there is no post-fetch hook, we check before we're about to run a hook.
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.2
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
- system("git checkout -q '#{File.basename(ref)}'")
101
+ output = %x(git checkout '#{File.basename(ref)}' 2>&1)
101
102
  if $? == 0
102
- STDERR.puts "Checked out #{File.basename(ref)}"
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
- system("git branch -f #{local_ref} #{ref}")
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
@@ -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
- FileUtils.mkdir_p(".git/hooks/shared")
21
- FileUtils.mkdir_p(".git/hooks/local")
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
- FileUtils.cp((ASSETS_PATH + "helpers/hookd_wrapper").to_s, ".git/hooks/#{hook}")
25
- FileUtils.chmod(0755, ".git/hooks/#{hook}")
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.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)
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
- 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
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
- target_hook_path = path
134
- base_directory = self.class.installed_path(install_kind)
135
- meta_data["targets"].each do |target|
136
- targetd_path = base_directory + "#{target}.d"
137
- rm_f(targetd_path + name)
138
- FileUtils.rmdir(targetd_path) if Dir.glob((targetd_path + "*").to_s).empty?
139
- end
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
 
@@ -2,6 +2,7 @@ class Gitty::HookCommand < Gitty::Runner
2
2
  COMMANDS = %w[
3
3
  init
4
4
  list
5
+ share
5
6
  show
6
7
  install
7
8
  uninstall
data/lib/gitty.rb CHANGED
@@ -26,6 +26,10 @@ module Gitty
26
26
  end
27
27
  nil
28
28
  end
29
+
30
+ def self.sharing_enabled?
31
+ File.exist?(".git/hooks/gitty/update-shared-hooks")
32
+ end
29
33
  end
30
34
 
31
35
  require "gitty/runner.rb"
@@ -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.3.7
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-10 00:00:00 -07:00
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