ruby_git_hooks 0.0.31
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/.gitignore +19 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +327 -0
- data/Rakefile +7 -0
- data/TODO +67 -0
- data/bin/git-add-hooks +111 -0
- data/bin/git-clone +57 -0
- data/bin/git-hclone +57 -0
- data/lib/ruby_git_hooks/all.rb +7 -0
- data/lib/ruby_git_hooks/case_clash.rb +30 -0
- data/lib/ruby_git_hooks/copyright_check.rb +181 -0
- data/lib/ruby_git_hooks/email_notify.rb +50 -0
- data/lib/ruby_git_hooks/git_ops.rb +93 -0
- data/lib/ruby_git_hooks/jira_add_comment.rb +354 -0
- data/lib/ruby_git_hooks/jira_ref_check.rb +32 -0
- data/lib/ruby_git_hooks/max_file_size.rb +32 -0
- data/lib/ruby_git_hooks/non_ascii.rb +33 -0
- data/lib/ruby_git_hooks/ruby_debug.rb +26 -0
- data/lib/ruby_git_hooks/version.rb +5 -0
- data/lib/ruby_git_hooks/watermark.rb +27 -0
- data/lib/ruby_git_hooks.rb +343 -0
- data/ruby_git_hooks.gemspec +37 -0
- data/test/basic_hook_test.rb +143 -0
- data/test/case_clash_hook_test.rb +58 -0
- data/test/copyright_check_test.rb +162 -0
- data/test/fake_curl +12 -0
- data/test/fake_mailer +5 -0
- data/test/jira_add_comment_test.rb +151 -0
- data/test/jira_ref_check_test.rb +37 -0
- data/test/max_file_size_hook_test.rb +52 -0
- data/test/multi_hook_test.rb +77 -0
- data/test/non_ascii_hook_test.rb +47 -0
- data/test/repos/.keep +0 -0
- data/test/test_helper.rb +17 -0
- data/test/watermark_test.rb +39 -0
- metadata +226 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--protected --no-private - *.md app/**/*.rb lib/**/*.rb --readme README.md
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 OL2, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,327 @@
|
|
1
|
+
# RubyGitHooks
|
2
|
+
|
3
|
+
RubyGitHooks sets up a reasonable development environment for git hooks.
|
4
|
+
|
5
|
+
Git, by default, gives you information that doesn't instantly map to
|
6
|
+
what you want. A pre-receive hook, for instance, doesn't just give
|
7
|
+
you the content that's being received. You have to extract the
|
8
|
+
content by running git commands. If you want to write a pre-receive
|
9
|
+
hook that can also be used pre-commit, you have to do a fair bit of
|
10
|
+
wrapping.
|
11
|
+
|
12
|
+
RubyGitHooks does that extracting and wrapping for your convenience.
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
To use with a single Ruby installation:
|
17
|
+
|
18
|
+
gem install ruby_git_hooks
|
19
|
+
|
20
|
+
Remember that ruby_git_hooks is invoked by Git -- it won't normally
|
21
|
+
run with Bundler. Not only do you not need to add it to your Gemfile,
|
22
|
+
it probably won't help. So make sure ruby_git_hooks is installed for
|
23
|
+
every Ruby you use day-to-day from the command line.
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
## Writing Hook Scripts
|
28
|
+
|
29
|
+
Your new hook script should have a Ruby shebang line (see below). You
|
30
|
+
can use the included hooks or define your own.
|
31
|
+
|
32
|
+
The hook should be copied or symlinked to the appropriate location, of
|
33
|
+
the form ".git/hooks/hook-name".
|
34
|
+
|
35
|
+
Here's an example: a pre-receive hook that uses the shebang line to
|
36
|
+
require ruby_git_hooks/case_clash, then runs it.
|
37
|
+
|
38
|
+
~~~
|
39
|
+
#!/usr/bin/env ruby
|
40
|
+
# Put this file in .git/hooks/pre-receive and make it executable!
|
41
|
+
require "ruby_git_hooks/case_clash"
|
42
|
+
|
43
|
+
RubyGitHooks.run CaseClashHook.new
|
44
|
+
~~~
|
45
|
+
|
46
|
+
### Multiple Git Hooks, One RubyGitHook
|
47
|
+
|
48
|
+
You can put a single hook script in and symlink it from one or more
|
49
|
+
git-hook locations:
|
50
|
+
|
51
|
+
~~~
|
52
|
+
> cp my_hook.rb .git/hooks/
|
53
|
+
> chmod +x .git/hooks/my_hook.rb
|
54
|
+
> ln -s .git/hooks/my_hook.rb .git/hooks/pre-commit
|
55
|
+
> ln -s .git/hooks/my_hook.rb .git/hooks/pre-receive
|
56
|
+
~~~
|
57
|
+
|
58
|
+
Use this when the hook is meaningful in more than one situation.
|
59
|
+
Watch out! You don't want four or five of the same email
|
60
|
+
notification.
|
61
|
+
|
62
|
+
### Multiple Hooks and RubyGitHooks.register
|
63
|
+
|
64
|
+
You can call register on multiple hooks and then run them:
|
65
|
+
|
66
|
+
~~~
|
67
|
+
#!/usr/bin/env ruby
|
68
|
+
# Put in .git/hooks/post-receive and make it executable!
|
69
|
+
require "ruby_git_hooks/case_clash"
|
70
|
+
require "ruby_git_hooks/copyright_check"
|
71
|
+
|
72
|
+
RubyGitHooks.register CaseClashHook.new
|
73
|
+
RubyGitHooks.register CopyrightCheck.new "domain" => "my_company.com",
|
74
|
+
"from" => "MyCo Inc. Copyright Reminders",
|
75
|
+
"via" => {
|
76
|
+
:address => "smtp.my_company.com",
|
77
|
+
:domain => "my_company.com"
|
78
|
+
}
|
79
|
+
|
80
|
+
RubyGitHooks.run # Run both
|
81
|
+
~~~
|
82
|
+
|
83
|
+
### Run By Git Hook Type
|
84
|
+
|
85
|
+
You can have a single RubyGitHook file and symlink it to all supported
|
86
|
+
git hooks. But then you probably don't want every RubyGitHook to run
|
87
|
+
for each type of git hook -- your pre-commit and post-commit hooks may
|
88
|
+
be different, for instance.
|
89
|
+
|
90
|
+
~~~
|
91
|
+
#!/usr/bin/env ruby
|
92
|
+
# Put in .git/hooks/post-receive and make it executable!
|
93
|
+
require "ruby_git_hooks/case_clash"
|
94
|
+
require "ruby_git_hooks/copyright_check"
|
95
|
+
|
96
|
+
if RubyGitHooks.current_hook =~ /pre-/
|
97
|
+
RubyGitHooks.run CaseClashHook.new
|
98
|
+
end
|
99
|
+
|
100
|
+
if RubyGitHooks.current_hook =~ /post-/
|
101
|
+
RubyGitHooks.run CopyrightCheck.new "domain" => "my_company.com",
|
102
|
+
"from" => "MyCo Inc. Copyright Reminders",
|
103
|
+
"via" => {
|
104
|
+
:address => "smtp.my_company.com",
|
105
|
+
:domain => "my_company.com"
|
106
|
+
}
|
107
|
+
end
|
108
|
+
~~~
|
109
|
+
|
110
|
+
### New Hook Types
|
111
|
+
|
112
|
+
You can declare a new hook type in your file if you like:
|
113
|
+
|
114
|
+
~~~
|
115
|
+
#!/usr/bin/env ruby
|
116
|
+
require "ruby_git_hooks"
|
117
|
+
|
118
|
+
class TestHook < RubyGitHooks::Hook
|
119
|
+
def check
|
120
|
+
fnords = file_contents.values.any? { |v| v.include?("fnord") }
|
121
|
+
|
122
|
+
puts "You may not check in the Fnords!" if fnords
|
123
|
+
|
124
|
+
!fnords
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
RubyGitHooks.run TestHook.new
|
129
|
+
~~~
|
130
|
+
|
131
|
+
### New Hooks on Clone
|
132
|
+
|
133
|
+
It's annoying that you don't automatically get hooks when you clone a
|
134
|
+
new repo. Often you want the same (or many of the same) hooks
|
135
|
+
everywhere -- don't allow incomplete merges to be re-committed, for
|
136
|
+
instance, or don't accept commit messages with non-ASCII characters.
|
137
|
+
|
138
|
+
Those preferences are specific to you, but not specific to the repo.
|
139
|
+
Clearly you should have a personal ~/.git_hooks directory containing
|
140
|
+
your preferred hooks, which are then copied into each new repo you
|
141
|
+
clone. Ruby_git_hooks does exactly that, but the commane is "git
|
142
|
+
hclone" instead of "git clone" unless you override it.
|
143
|
+
|
144
|
+
You can also call "git add-hooks" to refresh the project's hooks from
|
145
|
+
your ~/.git_hooks directory, in case your hooks have changed or files
|
146
|
+
may have been corrupted. This also works if you cloned without hooks
|
147
|
+
or otherwise have an existing repository without your hooks.
|
148
|
+
|
149
|
+
#### Using .bashrc to Override Git Clone
|
150
|
+
|
151
|
+
To override "git clone" itself, you'll need a hack to your .bashrc
|
152
|
+
The hack below allows you to add an executable like
|
153
|
+
"git-clone" to your path and have it be used in preference to the
|
154
|
+
regular git-clone in `git --exec-path`.
|
155
|
+
|
156
|
+
You can also skip this hack and always use "git hclone" instead of
|
157
|
+
"git clone" if you want hooks installed.
|
158
|
+
|
159
|
+
~~~
|
160
|
+
# NOTE: Stolen from http://stackoverflow.com/questions/2500586/setting-git-default-flags-on-commands
|
161
|
+
# Git supports aliases defined in .gitconfig, but you cannot override Git
|
162
|
+
# builtins (e.g. "git log") by putting an executable "git-log" somewhere in the
|
163
|
+
# PATH. Also, git aliases are case-insensitive, but case can be useful to create
|
164
|
+
# a negated command (gf = grep --files-with-matches; gF = grep
|
165
|
+
# --files-without-match). As a workaround, translate "X" to "-x".
|
166
|
+
git()
|
167
|
+
{
|
168
|
+
typeset -r gitAlias="git-$1"
|
169
|
+
if 'which' "$gitAlias" >/dev/null 2>&1; then
|
170
|
+
shift
|
171
|
+
"$gitAlias" "$@"
|
172
|
+
elif [[ "$1" =~ [A-Z] ]]; then
|
173
|
+
# Translate "X" to "-x" to enable aliases with uppercase letters.
|
174
|
+
translatedAlias=$(echo "$1" | sed -e 's/[A-Z]/-\l\0/g')
|
175
|
+
shift
|
176
|
+
"$(which git)" "$translatedAlias" "$@"
|
177
|
+
else
|
178
|
+
"$(which git)" "$@"
|
179
|
+
fi
|
180
|
+
}
|
181
|
+
~~~
|
182
|
+
|
183
|
+
### Using RubyGitHooks with RVM
|
184
|
+
|
185
|
+
To install ruby_git_hooks on RVM in all Rubies and gemsets:
|
186
|
+
|
187
|
+
rvm all do bash -l -c "rvm use @global && gem install ruby_git_hooks"
|
188
|
+
|
189
|
+
If you install a new Ruby then you'll need to install ruby_git_hooks
|
190
|
+
in its global gemset as well. Also, you'll need to install any gems
|
191
|
+
that your own personal hooks use, also in all gemsets.
|
192
|
+
|
193
|
+
If you don't want to do that, you'll need to create an rvm wrapper and
|
194
|
+
use it for the shebang line -- see below.
|
195
|
+
|
196
|
+
If you're using Git 1.7.X rather than 1.8.X, Git will prepend /usr/bin
|
197
|
+
to your path before running your hook -- you'll probably get the
|
198
|
+
system Ruby by accident instead of the one you want. You can upgrade
|
199
|
+
to Git 1.8.X, or create an rvm wrapper and use that.
|
200
|
+
|
201
|
+
To create an rvm wrapper:
|
202
|
+
|
203
|
+
rvm wrapper 1.9.3 githooks ruby
|
204
|
+
|
205
|
+
You can give your own Ruby version instead of 1.9.3, and an optional
|
206
|
+
gemset if you want the git hooks to use one. Then see "Using
|
207
|
+
RubyGitHooks with a Custom Shebang Line" below.
|
208
|
+
|
209
|
+
### Using RubyGitHooks with a Custom Shebang Line
|
210
|
+
|
211
|
+
If you don't want to use your current Ruby (with Git 1.8.X) or system
|
212
|
+
Ruby (with Git 1.7.X), you'll need to set the shebang line for your
|
213
|
+
hooks to the appropriate interpreter.
|
214
|
+
|
215
|
+
If you're creating your own hook files, it's clear how to do this.
|
216
|
+
|
217
|
+
But for RubyGitHooks' unit tests and generated hooks, you'll need to
|
218
|
+
tell it what shebang line to use.
|
219
|
+
|
220
|
+
Set it as an environment variable:
|
221
|
+
|
222
|
+
> export RUBYGITHOOKS_SHEBANG='#!/usr/bin/env /home/UserName/.rvm/bin/githooks_ruby'
|
223
|
+
|
224
|
+
You need this set when generating hook scripts or running the unit
|
225
|
+
tests of RubyGitHooks itself, but not later when using the hooks.
|
226
|
+
|
227
|
+
You need the /usr/bin/env in it because your wrapper is a shellscript,
|
228
|
+
and a shebang can't point to another shellscript on most systems.
|
229
|
+
|
230
|
+
### API and Hook Documentation
|
231
|
+
|
232
|
+
Documentation of individual hooks can be found in the YARD docs:
|
233
|
+
|
234
|
+
gem install yard redcarpet
|
235
|
+
yardoc
|
236
|
+
# Now open doc/_index.html in a browser of your choice
|
237
|
+
|
238
|
+
## Compatibility
|
239
|
+
|
240
|
+
This library is tested primarily on Mac OS X with Git 1.8.X, RVM and
|
241
|
+
Ruby 1.9.X.
|
242
|
+
|
243
|
+
It should be compatible with Git 1.7.X, Ruby 2.0.X and other Unix-like
|
244
|
+
systems.
|
245
|
+
|
246
|
+
It is *not* expected to work on Ruby 1.8.X. Please upgrade.
|
247
|
+
|
248
|
+
It is *not* expected to work on Windows systems. We would accept
|
249
|
+
patches to help fix this, but I don't know how reasonable it will be.
|
250
|
+
Git on Windows is often problematic.
|
251
|
+
|
252
|
+
It should be usable on non-RVM systems, including those using other
|
253
|
+
Ruby version managers like rbenv.
|
254
|
+
|
255
|
+
## Troubleshooting
|
256
|
+
|
257
|
+
### It Says It's Not Installed
|
258
|
+
|
259
|
+
Sometimes you can get an error saying that ruby_git_hooks isn't
|
260
|
+
installed when you try a git operation.
|
261
|
+
|
262
|
+
Simple stuff to try:
|
263
|
+
|
264
|
+
* Reinstall ruby_git_hooks in all RVM Rubies (see INSTALLATION) and
|
265
|
+
the system Ruby, if any.
|
266
|
+
|
267
|
+
* Upgrade Git to 1.8.2 or higher.
|
268
|
+
|
269
|
+
* If you don't use /usr/bin/ruby, move it to /usr/bin/old_ruby so it
|
270
|
+
doesn't get in the way. Your system Ruby is probably ancient Ruby
|
271
|
+
1.8.7 and everything sane uses 1.9.2 or higher.
|
272
|
+
|
273
|
+
Obvious problems:
|
274
|
+
|
275
|
+
* Not installed. Fix this for the Ruby or gemset that git runs.
|
276
|
+
|
277
|
+
* Running in a wrong/unexpected Ruby. Often this is /usr/bin/ruby,
|
278
|
+
the system Ruby and/or Ruby 1.8.7. You can move the bad Ruby out of
|
279
|
+
the way. Or you can install ruby_git_hooks into it. Or you can
|
280
|
+
adjust paths, shebang lines and environment variables to make git
|
281
|
+
run the right Ruby. Note that Git 1.7 adds /usr/bin to the front of
|
282
|
+
your path so you may get an expected Ruby. Git 1.8 does not.
|
283
|
+
Consider upgrading.
|
284
|
+
|
285
|
+
* Running in Bundler without meaning to. If your hook's shebang
|
286
|
+
includes or can run Bundler and you're using a Gemfile without
|
287
|
+
ruby_git_hooks then it's basically not installed. Usually the right
|
288
|
+
answer is "don't run Bundler for your git hooks." Otherwise you'll
|
289
|
+
have to add ruby_git_hooks to your Gemfile and/or add a new Gemfile
|
290
|
+
to .git/hooks.
|
291
|
+
|
292
|
+
### Ruby 1.8.7
|
293
|
+
|
294
|
+
We specifically do not test on Ruby 1.8.7.
|
295
|
+
|
296
|
+
We don't try to sabotage it, but it's not on our radar.
|
297
|
+
|
298
|
+
There's a good chance that ruby_git_hooks doesn't work on 1.8.7 at any
|
299
|
+
given time. This won't change. Ruby 1.8.7 is ancient and as of June
|
300
|
+
2013 will no longer even receive security fixes. Please upgrade.
|
301
|
+
Seriously, it's time.
|
302
|
+
|
303
|
+
We *do* support systems like Macs with 1.8.7 as /usr/bin/ruby. But
|
304
|
+
you may need a custom shebang line with an rvm wrapper.
|
305
|
+
|
306
|
+
### Git 1.7
|
307
|
+
|
308
|
+
Git 1.7 has had some problems, and may have more. Specifically:
|
309
|
+
|
310
|
+
* Git 1.7 does not set up parent-branch tracking by default, and
|
311
|
+
some of our unit tests may require that.
|
312
|
+
* Git 1.7 prepends /usr/bin to the path when running hooks (see above).
|
313
|
+
|
314
|
+
We make a best effort to support it, but 1.8 is a smoother experience.
|
315
|
+
|
316
|
+
## Contributing to RubyGitHooks
|
317
|
+
|
318
|
+
1. Fork it
|
319
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
320
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
321
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
322
|
+
5. Create new Pull Request
|
323
|
+
|
324
|
+
## License and Copying
|
325
|
+
|
326
|
+
Ruby Git Hooks is released under the MIT License by OL2, Inc.
|
327
|
+
Please see the file LICENSE.txt for a copy of this license.
|
data/Rakefile
ADDED
data/TODO
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
* Move this file's contents into GitHub issues, once we have a public GitHub repo for it.
|
2
|
+
|
3
|
+
* Convert to using Grit in git_ops.rb
|
4
|
+
|
5
|
+
* Do on-demand loading of Git information, so if no hook uses an
|
6
|
+
expensive Git operation, it can be skipped. The API allows it but
|
7
|
+
the implementation isn't in place yet.
|
8
|
+
|
9
|
+
* "Illegal content" hook -- for catching incomplete merges (">>>>>>"), etc.
|
10
|
+
|
11
|
+
* "Bundle install on pull" hook
|
12
|
+
|
13
|
+
* Wire up pre-rebase hooks to allow validations for multi-file
|
14
|
+
criteria. Then you can't rebase in a new file if it would violate
|
15
|
+
the CaseClashHook, say.
|
16
|
+
|
17
|
+
* A hook should have default hook types and file extensions and
|
18
|
+
git-hook names, and should only run if those match -- or if
|
19
|
+
registered with an overrriding git-hook name or file type.
|
20
|
+
|
21
|
+
* Add option registration to Hook parent class and do appropriate
|
22
|
+
string/symbol checking there.
|
23
|
+
|
24
|
+
* Print message if a hook is registered but run is never called.
|
25
|
+
|
26
|
+
* Use SimpleCov to check coverage in test_helper.rb
|
27
|
+
|
28
|
+
* Have a simple way to "forward" to another file. That is, save the
|
29
|
+
arguments and STDIN and call another file with the same arguments
|
30
|
+
and same STDIN. That would make it easy to have a "pre-commit.d"
|
31
|
+
directory and automatically call to every executable in that
|
32
|
+
directory matching "pre-commit" in the filename. Then you could
|
33
|
+
easily combine multiple hooks -- for instance, the cloner's personal
|
34
|
+
hooks, the workplace's at-work hooks and the project's supplied
|
35
|
+
hooks. Wouldn't always be a good idea, of course.
|
36
|
+
|
37
|
+
* Document (and figure out) how to write new hooks that aren't part of RubyGitHooks gem
|
38
|
+
There are details about how directories and environment variables are set
|
39
|
+
up by git when the hooks are called that can affect things like includes done by the hook.
|
40
|
+
For example most hooks are called with GIT_DIR set to .git and the working directory
|
41
|
+
set to the repo root BUT pre and post-receive are called with GIT_DIR set to '.'
|
42
|
+
and the working directory set to <repo root>/.git.
|
43
|
+
|
44
|
+
* Project-specific hooks. Right now, create a post-clone hook in
|
45
|
+
~/.git_hooks that looks for a /.hooks directory in the newly-created
|
46
|
+
repo and copies the hooks into ~/.git_hooks. Note that for now
|
47
|
+
these hooks will then *override* your personal ones. TODO: merge them.
|
48
|
+
|
49
|
+
* Where tests have "assert_raises RuntimeError", find a more specific
|
50
|
+
error. This occurs in several places.
|
51
|
+
|
52
|
+
* In copyright_check_hook, use regexp#scan instead of first match.
|
53
|
+
|
54
|
+
* In copyright_check_hook, allow passing the top-level regexp/check as
|
55
|
+
an option. This will require documenting that it overrides some other
|
56
|
+
things like the company check option.
|
57
|
+
|
58
|
+
* In jira_ref_check_hook, allow passing in list of legal statuses.
|
59
|
+
|
60
|
+
* In jira_ref_check_hook and jira_add_comment_hook, figure out how to
|
61
|
+
deal with checking with the server to see if a bug is real and
|
62
|
+
valid. This will be a tricky UI issue.
|
63
|
+
|
64
|
+
* In jira_add_comment_hook, rescue DNS errors for VPN setups. Allow
|
65
|
+
the commit, but print a message.
|
66
|
+
|
67
|
+
* In ruby_git_hooks.rb, have "shell!" capture both STDOUT and STDERR.
|
data/bin/git-add-hooks
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copy files from ~/.git_hooks into .git/hooks in the current repo.
|
4
|
+
|
5
|
+
# This script is run by Git, and can wind up running in system Ruby,
|
6
|
+
# so it should be as 1.8-compatible and low on dependencies as
|
7
|
+
# possible. I will be so, so happy when Ruby 1.8 is effectively
|
8
|
+
# dead.
|
9
|
+
|
10
|
+
# Note that we copy files that aren't names of hooks on purpose.
|
11
|
+
# It's totally kosher to have required or symlinked Ruby scripts
|
12
|
+
# and other stuff in the ~/.git_hooks dir. It's also totally
|
13
|
+
# kosher to use RubyGitHooks support for git clone with hooks
|
14
|
+
# even if you don't use RGH for anything else.
|
15
|
+
|
16
|
+
# When the system we are running on doesn't support symlinks,
|
17
|
+
# we turn the symlinks into wrapper scripts (for Windows, etc)
|
18
|
+
|
19
|
+
# As a support for the user's specific installation (a kind of
|
20
|
+
# install hooks hook) the file "pre-install-hook" will be run, if present
|
21
|
+
# if the pre-install-hook returns a non-zero error code, don't install
|
22
|
+
# the other files.
|
23
|
+
|
24
|
+
require "fileutils"
|
25
|
+
INSTALL_HOOK_SCRIPT = "pre-install-hook"
|
26
|
+
|
27
|
+
def system_supports_symlinks
|
28
|
+
# if we're on windows we won't recognize symlinks
|
29
|
+
# TO DO: we shouldn't test until we encounter one, but only test once)
|
30
|
+
begin
|
31
|
+
File.readlink("any file")
|
32
|
+
rescue NotImplementedError
|
33
|
+
puts "(Your system does not support symbolic links.)"
|
34
|
+
return false
|
35
|
+
rescue
|
36
|
+
# just ignore any other errors
|
37
|
+
end
|
38
|
+
return true
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_symlink(file)
|
42
|
+
# is this file supposed to be a symbolic link?
|
43
|
+
# if so it will contain just the name of the file it should be linked to.
|
44
|
+
# We could just read in part of the file if it's a longer file.
|
45
|
+
# Is it safe to just read the first line and check that?
|
46
|
+
contents = File.read(file) rescue nil
|
47
|
+
m = contents && contents.match(/\A\s*(\w*[\.]?\w*)\s*\z/)
|
48
|
+
return m && m[1]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Hack to allow git-add-hooks to be called from outide the git directory
|
52
|
+
# with the name of the git directory passed in. Addresses the problem
|
53
|
+
# of .rvmrc using a gemset that doesn't have rubygithooks and hence
|
54
|
+
# doesn't have git add-hooks.
|
55
|
+
if ARGV[0] && Dir.exist?(ARGV[0])
|
56
|
+
STDERR.puts "Installing into #{ARGV[0]}"
|
57
|
+
Dir.chdir(ARGV[0])
|
58
|
+
end
|
59
|
+
|
60
|
+
until File.exist?(".git") || Dir.getwd =~ /\/$/
|
61
|
+
Dir.chdir ".."
|
62
|
+
end
|
63
|
+
|
64
|
+
raise "You're not in a git directory!" unless File.exist?(".git")
|
65
|
+
Dir.mkdir(".git/hooks") unless File.exists?(".git/hooks")
|
66
|
+
|
67
|
+
source_dir = "#{ENV['HOME']}/.git_hooks"
|
68
|
+
raise "There's no #{source_dir} directory." unless File.exist?(source_dir)
|
69
|
+
|
70
|
+
# run pre-install-hook, if it exists
|
71
|
+
hook_file = "#{source_dir}/#{INSTALL_HOOK_SCRIPT}"
|
72
|
+
if File.exist?(hook_file)
|
73
|
+
puts "Running #{INSTALL_HOOK_SCRIPT} script."
|
74
|
+
if `echo $0` =~ /\$0/
|
75
|
+
# our ruby doesn't know about the shell and
|
76
|
+
# won't respect the shebang (e.g. we're in windows)
|
77
|
+
ruby_cmd = "#{Config::CONFIG['bindir']}/#{Config::CONFIG['ruby_install_name']}"
|
78
|
+
result = system("#{ruby_cmd} #{hook_file}")
|
79
|
+
else
|
80
|
+
result = system(hook_file) # run the hook
|
81
|
+
end
|
82
|
+
|
83
|
+
if !result
|
84
|
+
puts "pre-install hook failed"
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
has_sym = system_supports_symlinks
|
91
|
+
|
92
|
+
Dir["#{source_dir}/*"].each do |file|
|
93
|
+
system "chmod +x \"#{file}\""
|
94
|
+
hook_name = file.split("/")[-1] #e.g. pre-commit
|
95
|
+
dest = ".git/hooks/" + hook_name
|
96
|
+
next if hook_name == INSTALL_HOOK_SCRIPT # don't copy the script
|
97
|
+
if !has_sym && (link_file = is_symlink(file))
|
98
|
+
puts "Installing shell wrapper for: #{file}"
|
99
|
+
File.open(dest, "w") do |f|
|
100
|
+
f.write("#!/bin/bash\n")
|
101
|
+
f.write("#{Dir.getwd}/.git/hooks/#{link_file} --hook #{hook_name} \"$@\"\n")
|
102
|
+
end
|
103
|
+
system "chmod +x \"#{dest}\""
|
104
|
+
else
|
105
|
+
# otherwise just copy the file.
|
106
|
+
puts "Installing hook file: #{file}"
|
107
|
+
FileUtils.copy_entry(file, dest, false, false, true)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
puts "Copied hooks into #{Dir.getwd}/.git/hooks."
|
data/bin/git-clone
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# This is used for git-clone and git-hclone. Git-clone exists in case
|
4
|
+
# the user overrides git() with a shell function to allow automatic
|
5
|
+
# git-clone-with-hooks.
|
6
|
+
|
7
|
+
# This script is run by Git, and can wind up running in system Ruby,
|
8
|
+
# so it should be as 1.8-compatible and low on dependencies as
|
9
|
+
# possible. I will be so, so happy when Ruby 1.8 is effectively
|
10
|
+
# dead.
|
11
|
+
dashdash = ARGV.find_index("--")
|
12
|
+
if dashdash
|
13
|
+
nondash = ARGV[(dashdash+1)..-1]
|
14
|
+
else
|
15
|
+
# These are the documented git-clone options that take an additional
|
16
|
+
# piece of data afterward, such as "-o someorigin".
|
17
|
+
ARGS_WITH_ARGS = %w(-o -b -u --reference --separate-git-dir --depth)
|
18
|
+
|
19
|
+
nodash = []
|
20
|
+
i = 0
|
21
|
+
while i < ARGV.length
|
22
|
+
if ARGV[i][0] != "-"
|
23
|
+
nodash.push ARGV[i]
|
24
|
+
elsif ARGS_WITH_ARGS.include?(ARGV[i])
|
25
|
+
i += 1
|
26
|
+
end # else ignore
|
27
|
+
|
28
|
+
i += 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# allow to override with --nohooks
|
33
|
+
nohooks = ARGV.delete("--nohooks") || ARGV.delete("--noHooks") || ARGV.delete("--no-hooks")
|
34
|
+
|
35
|
+
if nodash.size > 1
|
36
|
+
dest_dir = nodash[-1]
|
37
|
+
elsif nodash.size == 1
|
38
|
+
# Cloning from a URI
|
39
|
+
dest_dir = nodash[-1].split("/")[-1].gsub(/\.git$/, "")
|
40
|
+
else
|
41
|
+
# No args? Huh.
|
42
|
+
dest_dir = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
system(File.join(`git --exec-path`.chomp, "git-clone"), *ARGV)
|
46
|
+
if $?.success?
|
47
|
+
if nohooks
|
48
|
+
STDERR.puts "Hooks not installed."
|
49
|
+
elsif dest_dir && File.exist?(dest_dir)
|
50
|
+
Dir.chdir dest_dir
|
51
|
+
system(File.join(File.dirname(__FILE__), "git-add-hooks"))
|
52
|
+
elsif dest_dir
|
53
|
+
STDERR.puts "Couldn't find directory #{dest_dir}. Hooks not installed."
|
54
|
+
else
|
55
|
+
STDERR.puts "Couldn't determine destination directory. Hooks not installed."
|
56
|
+
end
|
57
|
+
end
|
data/bin/git-hclone
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# This is used for git-clone and git-hclone. Git-clone exists in case
|
4
|
+
# the user overrides git() with a shell function to allow automatic
|
5
|
+
# git-clone-with-hooks.
|
6
|
+
|
7
|
+
# This script is run by Git, and can wind up running in system Ruby,
|
8
|
+
# so it should be as 1.8-compatible and low on dependencies as
|
9
|
+
# possible. I will be so, so happy when Ruby 1.8 is effectively
|
10
|
+
# dead.
|
11
|
+
dashdash = ARGV.find_index("--")
|
12
|
+
if dashdash
|
13
|
+
nondash = ARGV[(dashdash+1)..-1]
|
14
|
+
else
|
15
|
+
# These are the documented git-clone options that take an additional
|
16
|
+
# piece of data afterward, such as "-o someorigin".
|
17
|
+
ARGS_WITH_ARGS = %w(-o -b -u --reference --separate-git-dir --depth)
|
18
|
+
|
19
|
+
nodash = []
|
20
|
+
i = 0
|
21
|
+
while i < ARGV.length
|
22
|
+
if ARGV[i][0] != "-"
|
23
|
+
nodash.push ARGV[i]
|
24
|
+
elsif ARGS_WITH_ARGS.include?(ARGV[i])
|
25
|
+
i += 1
|
26
|
+
end # else ignore
|
27
|
+
|
28
|
+
i += 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# allow to override with --nohooks
|
33
|
+
nohooks = ARGV.delete("--nohooks") || ARGV.delete("--noHooks") || ARGV.delete("--no-hooks")
|
34
|
+
|
35
|
+
if nodash.size > 1
|
36
|
+
dest_dir = nodash[-1]
|
37
|
+
elsif nodash.size == 1
|
38
|
+
# Cloning from a URI
|
39
|
+
dest_dir = nodash[-1].split("/")[-1].gsub(/\.git$/, "")
|
40
|
+
else
|
41
|
+
# No args? Huh.
|
42
|
+
dest_dir = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
system(File.join(`git --exec-path`.chomp, "git-clone"), *ARGV)
|
46
|
+
if $?.success?
|
47
|
+
if nohooks
|
48
|
+
STDERR.puts "Hooks not installed."
|
49
|
+
elsif dest_dir && File.exist?(dest_dir)
|
50
|
+
Dir.chdir dest_dir
|
51
|
+
system(File.join(File.dirname(__FILE__), "git-add-hooks"))
|
52
|
+
elsif dest_dir
|
53
|
+
STDERR.puts "Couldn't find directory #{dest_dir}. Hooks not installed."
|
54
|
+
else
|
55
|
+
STDERR.puts "Couldn't determine destination directory. Hooks not installed."
|
56
|
+
end
|
57
|
+
end
|