|
1 #!/usr/bin/env ruby |
|
2 |
|
3 # Meant for use as a git hook: |
|
4 # CTAGS_HOOK=1 ~/.git_helpers/ctags &>/dev/null </dev/null & |
|
5 # or an aliased cmd on demand: |
|
6 # git config alias.ctags '!.git/hooks/ctags' |
|
7 # or disable when you wish: |
|
8 # CTAGS_SKIP=1 git rebase |
|
9 |
|
10 # Create a tags file (target) using git's list of tracked files. If |
|
11 # .git/ctags.conf exists in the repo it is passed to the ctags invocation. |
|
12 # |
|
13 # When run w/o env, immediately run ctags and replace tags file. |
|
14 # |
|
15 # When run with CTAGS_HOOK, it's assumed to be a BG process and we want to wait |
|
16 # for git to be done applying changes no matter how the hook is triggered. |
|
17 # Wait five seconds, then bail if we can't get a lock on the tags file or if |
|
18 # it's been updated within the last minute. Only then, run ctags and replace |
|
19 # the tags file. |
|
20 |
|
21 exit if ENV['CTAGS_SKIP'] |
|
22 |
|
23 ctags = 'ctags' |
|
24 |
|
25 dir = `git rev-parse --show-toplevel`.chomp |
|
26 |
|
27 conf = "#{dir}/.git/ctags.conf" |
|
28 target = "#{dir}/.tags" |
|
29 tmp = "#{dir}/.tags.#{$$}~" |
|
30 |
|
31 opts = File.exists?(conf) ? "--options=#{conf}" : '' |
|
32 |
|
33 sleep 5 if ENV['CTAGS_HOOK'] |
|
34 |
|
35 open(target, File::RDONLY|File::CREAT, 0644) do |f| |
|
36 if ENV['CTAGS_HOOK'] |
|
37 exit unless f.flock(File::LOCK_EX|File::LOCK_NB) |
|
38 exit unless (Time.now - f.mtime) > 60 |
|
39 end |
|
40 |
|
41 system(<<-CMD) or exit $?.exitstatus |
|
42 git ls-files \ |
|
43 | #{ctags} --tag-relative -L - -f"#{tmp}" #{opts} \ |
|
44 && mv #{tmp} #{target} |
|
45 CMD |
|
46 end |
|
47 |
|
48 |
|
49 |