bin/git-ctags

changeset 445
1201037900f5
parent 443
e731ef81637c
child 446
acd0b08d467e
equal deleted inserted replaced
444:1e9fc079c697 445:1201037900f5
1 #!/usr/bin/env ruby 1 #!/usr/bin/env ruby
2 exit if ENV['CTAGS_SKIP'] 2 exit if ENV['CTAGS_SKIP']
3 ARGV.each { |o| exec('perldoc', $0) if o.match('help') } 3 running_hook = ENV['CTAGS_HOOK'] || false
4 ctags_cmd = ENV['CTAGS_CMD'] || 'ctags'
4 5
5 ctags_bin = ENV['CTAGS_BIN'] || 'ctags' 6 case ARGV[0]
7 when 'help'
8 exec 'perldoc', $0
9 when 'hook'
10 running_hook = true
11 end
6 12
7 if (dir = `git rev-parse --show-toplevel 2>/dev/null`.chomp) != '' 13 if (dir = `git rev-parse --show-toplevel 2>/dev/null`.chomp) != ''
8 list_cmd = 'git ls-files' 14 list_cmd = 'git ls-files'
9 conf = "#{dir}/.git/ctags.conf" 15 conf = "#{dir}/.git/ctags.conf"
10 elsif (dir = `hg root 2>/dev/null`.chomp) != '' 16 elsif (dir = `hg root 2>/dev/null`.chomp) != ''
14 abort 'not an hg or git repository' 20 abort 'not an hg or git repository'
15 end 21 end
16 22
17 target = "#{dir}/.tags" 23 target = "#{dir}/.tags"
18 tmp = "#{dir}/.tags.#{$$}~" 24 tmp = "#{dir}/.tags.#{$$}~"
19
20 opts = File.exists?(conf) ? "--options=#{conf}" : '' 25 opts = File.exists?(conf) ? "--options=#{conf}" : ''
21 26
22 if ENV['CTAGS_HOOK'] 27 if running_hook
23 fork and exit 28 fork and exit
24 sleep 5 29 sleep 5
25 end 30 end
26 31
27 open(target, File::RDONLY|File::CREAT, 0644) do |f| 32 open(target, File::RDONLY|File::CREAT, 0644) do |f|
28 if ENV['CTAGS_HOOK'] 33 if running_hook
29 exit unless f.flock(File::LOCK_EX|File::LOCK_NB) 34 exit unless f.flock(File::LOCK_EX|File::LOCK_NB)
30 exit unless (Time.now - f.mtime) > 60 35 exit unless (Time.now - f.mtime) > 60
31 end 36 end
32 37
33 system(<<-CMD) or exit $?.exitstatus 38 system(<<-CMD) or exit $?.exitstatus
34 #{list_cmd} \ 39 #{list_cmd} \
35 | #{ctags_bin} --tag-relative -L - -f"#{tmp}" #{opts} \ 40 | #{ctags_cmd} --tag-relative -L - -f"#{tmp}" #{opts} \
36 && mv #{tmp} #{target} 41 && mv #{tmp} #{target}
37 CMD 42 CMD
38 end 43 end
39 44
40 exit 0 45 exit 0
41 46
42 <<'=cut' 47 __END__
43 =head1 NAME 48 =head1 NAME
44 49
45 git-ctags - run ctags on git tracked files 50 git-ctags - run ctags on git tracked files
46 51
47 =head1 SYNOPSIS 52 =head1 SYNOPSIS
48 53
49 git ctags 54 git ctags
50 55
51 echo 'CTAGS_HOOK=1 git ctags' >> .git/hooks/post-checkout 56 echo 'git ctags hook 2>/dev/null' >> .git/hooks/post-checkout
52 57
53 git checkout some/branch 58 git checkout some/branch
54 CTAGS_SKIP=1 git checkout some/branch 59 CTAGS_SKIP=1 git checkout some/branch
55 60
56 =head1 DESCRIPTION 61 =head1 DESCRIPTION
57 62
58 Create a .tags file (target) using git's list of tracked files. If 63 Create a .tags file (target) using git's list of tracked files. If
59 C<.git/ctags.conf> exists in the repo it is passed to the ctags invocation. 64 C<.git/ctags.conf> exists in the repo it is passed to the ctags invocation.
60 65
61 When run with C<CTAGS_HOOK> set, additional behavior is enabled to avoid excess 66 When run with the C<hook> argument or C<CTAGS_HOOK> set, additional behavior is
62 re-runs during multiple VCS operations, and the work is moved to background as 67 enabled to avoid excess re-runs during multiple VCS operations, and the work is
63 well. 68 moved to background as well.
64 69
65 =head2 Mercurial 70 =head2 Mercurial
66 71
67 Mercurial repositories are supported too, with git taking priority when finding 72 Mercurial repositories are supported too, with git taking priority when finding
68 a repo root. To add a hook, in the repository C<.hg/hgrc>, add: 73 a repo root. To add a hook, in the repository C<.hg/hgrc>, add:
69 74
70 [hooks] 75 [hooks]
71 update = CTAGS_HOOK=1 git ctags 76 update = git ctags hook
72 77
73 In a Mercurial repo, additional options can be put in C<.hg/ctags.conf>. 78 In a Mercurial repo, additional options can be put in C<.hg/ctags.conf>.
74 79
75 =head1 ENVIRONMENT 80 =head1 ENVIRONMENT
76 81
77 =head2 CTAGS_SKIP 82 =head2 CTAGS_SKIP
78 83
79 If true, exit immediately. 84 If defined, exit immediately.
80 85
81 =head2 CTAGS_HOOK 86 =head2 CTAGS_HOOK
82 87
83 If true, run as a VCS hook. This causes git-ctags to fork and exit, wait five 88 If defined, run as a VCS hook. This causes git-ctags to fork and exit, wait five
84 seconds, then try to lock and update the tags file if it hasn't been updated in 89 seconds, then try to lock and update the tags file if it hasn't been updated in
85 the last minute. 90 the last minute.
86 91
87 =head2 CTAGS_BIN 92 =head2 CTAGS_CMD
88 93
89 If set, use this to invoke ctags rather than assuming C<ctags> can be found in 94 If defined, use this to invoke ctags rather than assuming C<ctags> can be found in
90 path. 95 path.
91 96
92 =cut 97 =cut

mercurial