ruby_git_hooks 0.0.31
Sign up to get free protection for your applications and to get access to all the features.
- 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
|