support hg in git-ctags, deduplicate hg helper stuff

Sat, 10 Dec 2016 16:42:04 -0500

author
Meredith Howard <mhoward@roomag.org>
date
Sat, 10 Dec 2016 16:42:04 -0500
changeset 443
e731ef81637c
parent 442
eefccfe398e9
child 444
1e9fc079c697

support hg in git-ctags, deduplicate hg helper stuff

.hg_helpers/ctags file | annotate | diff | comparison | revisions
.hg_helpers/hooks/ctags-hook file | annotate | diff | comparison | revisions
.hgrc file | annotate | diff | comparison | revisions
bin/git-ctags file | annotate | diff | comparison | revisions
deleted file mode 100755
--- a/.hg_helpers/ctags
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env ruby
-
-# Meant for use as a git hook:
-#   CTAGS_HOOK=1 .git/hooks/ctags &>/dev/null </dev/null &
-# or an aliased cmd on demand:
-#   git config alias.ctags '!.git/hooks/ctags'
-# or disable when you wish:
-#   CTAGS_SKIP=1 git rebase
-
-exit if ENV['CTAGS_SKIP']
-
-ctags  = "/opt/local/bin/ctags"
-ctags  = 'ctags' if !File.exists?(ctags)
-
-dir    = `hg root`.chomp
-
-conf   = "#{dir}/.ctags.conf"
-target = "#{dir}/.tags"
-tmp    = "#{dir}/#{$$}.tags"
-
-opts   = File.exists?(conf) ? "--options=#{conf}" : ''
-
-sleep 5 if ENV['CTAGS_HOOK']
-
-open( target, File::RDONLY|File::CREAT, 0644 ) do |f|
-  if ENV['CTAGS_HOOK']
-    exit unless f.flock( File::LOCK_EX|File::LOCK_NB )
-    exit unless ( Time.now - f.mtime ) > 60
-  end
-
-  system( <<-CMD ) or exit $?.exitstatus
-    hg stat -Aqn \
-     | #{ctags} --tag-relative -L - -f"#{tmp}" #{opts} \
-    && mv #{tmp} #{target}
-  CMD
-end
-
-
-
deleted file mode 100755
--- a/.hg_helpers/hooks/ctags-hook
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-# in repo .hg/hgrc:
-# [hooks]
-# changegroup = ~/.hg_helpers/hooks/ctags-hook
-export CTAGS_HOOK=1
-~/.hg_helpers/ctags </dev/null >/dev/null 2>&1 &
--- a/.hgrc
+++ b/.hgrc
@@ -19,7 +19,7 @@ pager = LESS='FSRX' less
 
 [alias]
 fetch = pull --rebase
-ctags = !~/.hg_helpers/ctags
+ctags = !~/bin/git-ctags
 
 [merge-tools]
 vimdiff.executable = vim
--- a/bin/git-ctags
+++ b/bin/git-ctags
@@ -2,17 +2,27 @@
 exit if ENV['CTAGS_SKIP']
 ARGV.each { |o| exec('perldoc', $0) if o.match('help') }
 
-ctags  = 'ctags'
+ctags_bin = ENV['CTAGS_BIN'] || 'ctags'
 
-dir    = `git rev-parse --show-toplevel`.chomp
+if (dir = `git rev-parse --show-toplevel 2>/dev/null`.chomp) != ''
+  list_cmd = 'git ls-files'
+  conf     = "#{dir}/.git/ctags.conf"
+elsif (dir = `hg root 2>/dev/null`.chomp) != ''
+  list_cmd = 'hg stat -Aqn'
+  conf     = "#{dir}/.hg/ctags.conf"
+else
+  abort 'not an hg or git repository'
+end
 
-conf   = "#{dir}/.git/ctags.conf"
 target = "#{dir}/.tags"
 tmp    = "#{dir}/.tags.#{$$}~"
 
 opts   = File.exists?(conf) ? "--options=#{conf}" : ''
 
-sleep 5 if ENV['CTAGS_HOOK']
+if ENV['CTAGS_HOOK']
+  fork and exit
+  sleep 5
+end
 
 open(target, File::RDONLY|File::CREAT, 0644) do |f|
   if ENV['CTAGS_HOOK']
@@ -21,8 +31,8 @@ open(target, File::RDONLY|File::CREAT, 0
   end
 
   system(<<-CMD) or exit $?.exitstatus
-    git ls-files \
-     | #{ctags} --tag-relative -L - -f"#{tmp}" #{opts} \
+    #{list_cmd} \
+     | #{ctags_bin} --tag-relative -L - -f"#{tmp}" #{opts} \
     && mv #{tmp} #{target}
   CMD
 end
@@ -38,7 +48,7 @@ git-ctags - run ctags on git tracked fil
 
  git ctags
 
- echo 'CTAGS_HOOK=1 git ctags &' >> .git/hooks/post-checkout
+ echo 'CTAGS_HOOK=1 git ctags' >> .git/hooks/post-checkout
 
  git checkout some/branch
  CTAGS_SKIP=1 git checkout some/branch
@@ -48,12 +58,35 @@ git-ctags - run ctags on git tracked fil
 Create a .tags file (target) using git's list of tracked files.  If
 C<.git/ctags.conf> exists in the repo it is passed to the ctags invocation.
 
-When run w/o env, immediately run ctags and replace tags file.
+When run with C<CTAGS_HOOK> set, additional behavior is enabled to avoid excess
+re-runs during multiple VCS operations, and the work is moved to background as
+well.
+
+=head2 Mercurial
+
+Mercurial repositories are supported too, with git taking priority when finding
+a repo root.  To add a hook, in the repository C<.hg/hgrc>, add:
+
+ [hooks]
+ update = CTAGS_HOOK=1 git ctags
+
+In a Mercurial repo, additional options can be put in C<.hg/ctags.conf>.
 
-When run with C<CTAGS_HOOK>, it's assumed to be a BG process and we want to
-wait for git to be done applying changes no matter how the hook is triggered.
-Wait five seconds, then bail if we can't get a lock on the tags file or if it's
-been updated within the last minute. Only then, run ctags and replace the tags
-file.
+=head1 ENVIRONMENT
+
+=head2 CTAGS_SKIP
+
+If true, exit immediately.
+
+=head2 CTAGS_HOOK
+
+If true, run as a VCS hook.  This causes git-ctags to fork and exit, wait five
+seconds, then try to lock and update the tags file if it hasn't been updated in
+the last minute.
+
+=head2 CTAGS_BIN
+
+If set, use this to invoke ctags rather than assuming C<ctags> can be found in
+path.
 
 =cut

mercurial