tagrity 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6a806ddd2c63796848d31f7937f7975b76c5e400530c9795fe256892edacfad
4
- data.tar.gz: d191e1bb5446cd583b3a3496bdfd10a3ef8ca9cbf5f55503ba99ac78e7f3e475
3
+ metadata.gz: 0ee6568e2b6eece64b41ea5bfd180aff6770f909d2ae0a2d1b113d6776913bf7
4
+ data.tar.gz: 963d36ade8dcae0fcf5f9457c057c2ca99984c0e6c27ca5d583bfee960b0fd0e
5
5
  SHA512:
6
- metadata.gz: '09f2854c20831ca036c19e6faa9af0575be22893b7601a3b0bc5ade5c2698a884509890fe5cd2a9b6fbdcfc2f8fc5873708b1c41af0abece7fab2b7f3d670fef'
7
- data.tar.gz: 7c294ab265efdddc4ffd9127ebb228dad290ce5e49ced15b131d70280871df3bc072f7931497357e750673029e9885d56e6bfead8d2047959c99917ce6725bb5
6
+ metadata.gz: 07b68faab753df68dd50a90c0059498b35f55de439fd228e04a93d246489b3db50073d148c644bce12007d2c119bd6deaa9c3a17156d2680fa36f3f87aeea26e
7
+ data.tar.gz: 73d254a884b320d83fa06c794a7e30940b29d7021915ae8c4374f5d34c675a9af2a2d25c55bf42f37704e93dbba49263d0e0bcc2ca14c82e46bc6709204a836c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tagrity (0.1.2)
4
+ tagrity (0.1.3)
5
5
  listen (~> 3.0)
6
6
  thor (~> 0.20)
7
7
 
data/README.md CHANGED
@@ -84,3 +84,44 @@ The gem is available as open source under the terms of the [MIT License](https:/
84
84
  ## Code of Conduct
85
85
 
86
86
  Everyone interacting in the Tagrity project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/tagrity/blob/master/CODE_OF_CONDUCT.md).
87
+
88
+
89
+
90
+
91
+ tagrity config to use (default to ~/.config/tagrity/config.yml if available).
92
+ A config file is a yaml file with the following possible values.
93
+ Some of these can be overridden with options, however the configfile
94
+ provided via --configfile will override the global config file in
95
+ ~/.config/tagrity/config.yml
96
+ ```
97
+ # ext_cmds allows different tag generators to be used depending on the file extension.
98
+ # Multiple extensions does not work, *.html.erb files will be picked up as erb.
99
+ # ext_cmds:
100
+ # <file extension>: <command to use to generate tags for this file extension>
101
+ # DEFAULT: empty
102
+ ext_cmds:
103
+ rb: ripper-tags
104
+ c: ctags
105
+ go: gotags
106
+
107
+ # default_cmd specifies the default command to be used to generate tags
108
+ # default_cmd: <command>
109
+ # DEFAULT: ctags
110
+ default_cmd: ctags
111
+
112
+ # tagf is the filename (relative) to generate tags into
113
+ # tagf: <filename>
114
+ # DEFAULT: tags
115
+ tagf: tags
116
+
117
+ # excluded_exts specifies which file extensions to not generate tags for.
118
+ # excluded_exts: [<file extension>, ...]
119
+ # DEFAULT: []
120
+ excluded_exts: [rb, h, js]
121
+
122
+ # excluded_paths specifies which paths to ignore.
123
+ # It's usually better to avoid this since by default tagrity will only look
124
+ # at files which are tracked by git.
125
+ # excluded_paths: [<path>, ...]
126
+ # DEFAULT: []
127
+ excluded_paths: [vendor, node_modules]
data/foobar.rb ADDED
File without changes
data/lib/tagrity/cli.rb CHANGED
@@ -6,16 +6,18 @@ require 'tagrity/commands/status'
6
6
  module Tagrity
7
7
  class CLI < Thor
8
8
  desc "start", "Start watching a directory (default to pwd)"
9
- option :dir
10
- option :fg, type: :boolean
11
- option :configfile
12
- option :tagf
13
- option :default_cmd
14
- option :excluded_exts, type: :array
15
- option :excluded_paths, type: :array
9
+ option :dir, desc: "directory to watch (omit to use pwd)"
10
+ option :fresh, type: :boolean, default: false, desc: "index the whole codebase before watching the file system."
11
+ option :tagf, desc: "filename (relative) to generate tags into (default: 'tags')."
12
+ option :git, type: :boolean, default: true, desc: "only index files which are being tracked by git"
13
+ option :fg, type: :boolean, desc: "keep the tagrity process running in the foreground"
14
+ option :configfile, desc: "See README for more info."
15
+ option :default_cmd, desc: "the default command to be used to generate tags (default: 'ctags')"
16
+ option :excluded_exts, type: :array, desc: "which file extensions to not generate tags for."
17
+ option :excluded_paths, type: :array, desc: "which paths to ignore. Usually better to ignore this since by default only file tracked by git are indexed."
16
18
  def start()
17
19
  setup_config
18
- Command::Start::call(dir, fg?)
20
+ Command::Start::call(dir, fg?, fresh?)
19
21
  end
20
22
 
21
23
  desc "stop", "Stop watching a directory (default to pwd)"
@@ -41,13 +43,18 @@ module Tagrity
41
43
  options[:fg]
42
44
  end
43
45
 
46
+ def fresh?
47
+ options[:fresh]
48
+ end
49
+
44
50
  def setup_config
45
51
  ConfigFile.instance.init(
46
52
  configfile: options[:configfile],
47
53
  default_cmd: options[:default_cmd],
48
54
  tagf: options[:tagf],
49
55
  excluded_exts: options[:excluded_exts],
50
- excluded_paths: options[:excluded_paths]
56
+ excluded_paths: options[:excluded_paths],
57
+ git: options[:git]
51
58
  )
52
59
  end
53
60
  end
@@ -1,6 +1,6 @@
1
1
  require 'listen'
2
2
  require 'tagrity/pid_file'
3
- require 'tagrity/process_helper'
3
+ require 'tagrity/helper'
4
4
  require 'tagrity/file_callbacks'
5
5
  require 'tagrity/provider'
6
6
 
@@ -10,7 +10,7 @@ module Tagrity
10
10
  class ErrorProcessAlreadyRunning < StandardError; end
11
11
 
12
12
  class << self
13
- def call(dir, fg)
13
+ def call(dir, fg, fresh)
14
14
  assert_not_running(dir)
15
15
 
16
16
  Process.daemon(nochdir: true) unless fg
@@ -18,9 +18,10 @@ module Tagrity
18
18
  callbacks = Provider.provide(:file_callbacks)
19
19
  PidFile.write(PidFile.new(dir, Process.pid))
20
20
 
21
+ callbacks.on_fresh if fresh
22
+
21
23
  listener = Listen.to(
22
24
  dir,
23
- ignore: [/^\.?tags$/],
24
25
  relative: true,
25
26
  ) do |modified, added, removed|
26
27
  callbacks.on_files_modified(modified)
@@ -1,19 +1,21 @@
1
1
  require 'yaml'
2
2
  require 'singleton'
3
- require 'tagrity/executable_helper'
3
+ require 'tagrity/helper'
4
4
 
5
5
  module Tagrity
6
6
  class ConfigFile
7
7
  include Singleton
8
8
 
9
9
  class ErrorTagFileNotWritable < StandardError; end
10
+ class ErrorGitNotExecutable < StandardError; end
10
11
 
11
12
  def init(
12
13
  configfile:,
13
14
  default_cmd:,
14
15
  tagf:,
15
16
  excluded_exts:,
16
- excluded_paths:
17
+ excluded_paths:,
18
+ git:
17
19
  )
18
20
  fname = config_file_name(configfile)
19
21
  @config = if fname.nil? then {} else YAML.load_file(fname) end
@@ -22,11 +24,12 @@ module Tagrity
22
24
  ensure_tagf(tagf)
23
25
  ensure_excluded_exts(excluded_exts)
24
26
  ensure_excluded_paths(excluded_paths)
27
+ ensure_git(git)
25
28
  end
26
29
 
27
30
  def ft_to_cmd(ext)
28
31
  ft_cmd = @config['ext_cmds'][ext]
29
- return @config['default_cmd'] if ft_cmd.nil? || !ExecutableHelper.is_executable(ft_cmd)
32
+ return @config['default_cmd'] if ft_cmd.nil? || !Helper.is_executable?(ft_cmd)
30
33
  ft_cmd
31
34
  end
32
35
 
@@ -42,6 +45,10 @@ module Tagrity
42
45
  @config['tagf']
43
46
  end
44
47
 
48
+ def respect_git?
49
+ @config['git']
50
+ end
51
+
45
52
  def to_s
46
53
  @config.to_s
47
54
  end
@@ -71,6 +78,13 @@ module Tagrity
71
78
  end
72
79
  end
73
80
 
81
+ def ensure_git(git)
82
+ set_option('git', git, true)
83
+ if @config['git'] && !Helper.is_executable?('git')
84
+ raise ErrorGitNotExecutable, "'git' must be executable to use the --git option."
85
+ end
86
+ end
87
+
74
88
  def set_option(key, local_val, default)
75
89
  unless local_val.nil?
76
90
  @config[key] = local_val
@@ -7,6 +7,10 @@ module Tagrity
7
7
  @tag_generator = tag_generator
8
8
  end
9
9
 
10
+ def on_fresh
11
+ @tag_generator.generate_all
12
+ end
13
+
10
14
  def on_files_modified(files)
11
15
  @tag_generator.generate(files)
12
16
  end
@@ -0,0 +1,57 @@
1
+ module Tagrity
2
+ class Helper
3
+ root = ENV['TEST'] ? __dir__ : "#{ENV['HOME']}/.tagrity/"
4
+ RUN_DIR = File.join(root, 'var/run').freeze
5
+ LOG_DIR = File.join(root, 'var/log').freeze
6
+
7
+ class << self
8
+ def run_dir
9
+ ensure_data_dirs
10
+ RUN_DIR
11
+ end
12
+
13
+ def is_executable?(cmd)
14
+ !%x{command -v #{cmd}}.empty?
15
+ end
16
+
17
+ def kill(pid)
18
+ Process.kill('HUP', pid)
19
+ end
20
+
21
+ def alive?(pid)
22
+ Process.kill(0, pid) # signal 0 checks if pid is alive
23
+ true
24
+ rescue Errno::ESRCH
25
+ false
26
+ rescue Errno::EPERM
27
+ true
28
+ end
29
+
30
+ def is_git_dir?
31
+ return @is_git_dir unless @is_git_dir.nil?
32
+ `git rev-parse --git-dir &> /dev/null`
33
+ if $?.exitstatus == 0
34
+ @is_git_dir = true
35
+ else
36
+ @is_git_dir = false
37
+ end
38
+ end
39
+
40
+ def is_file_ignored?(file)
41
+ `git check-ignore -q #{file} &> /dev/null`
42
+ $?.exitstatus == 0
43
+ end
44
+
45
+ def is_file_tracked?(file)
46
+ `git ls-files --error-unmatch #{file} &> /dev/null`
47
+ $?.exitstatus == 0
48
+ end
49
+
50
+ private
51
+
52
+ def ensure_data_dirs
53
+ FileUtils.mkdir_p(RUN_DIR)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,31 +1,31 @@
1
+ require 'tagrity/helper'
2
+
1
3
  module Tagrity
2
4
  class PidFile
3
- RUN_DIR = "#{ENV['HOME']}/.tagrity/var/run"
4
-
5
5
  class << self
6
6
  def write(pid_file)
7
- File.write("#{run_dir}/#{pid_file.name}", pid_file.dir)
7
+ File.write("#{Helper.run_dir}/#{pid_file.name}", pid_file.dir)
8
8
  end
9
9
 
10
10
  def delete(dir)
11
- pid_file_paths = Dir.glob("#{run_dir}/#{dir.split('/').last}.*.pid").select do |path|
11
+ pid_file_paths = Dir.glob("#{Helper.run_dir}/#{dir.split('/').last}.*.pid").select do |path|
12
12
  full_dir = File.read(path)
13
13
  File.realdirpath(full_dir) == File.realdirpath(dir)
14
14
  end
15
15
 
16
16
  pid_file_paths.each do |path|
17
17
  File.delete(path)
18
- ProcessHelper.kill(pid_from_path(path))
18
+ Helper.kill(pid_from_path(path))
19
19
  end
20
20
  end
21
21
 
22
22
  def alive_pid_files(dir: nil)
23
- Dir.glob("#{run_dir}/*").reduce([]) do |pid_files, path|
23
+ Dir.glob("#{Helper.run_dir}/*").reduce([]) do |pid_files, path|
24
24
  pid = pid_from_path(path)
25
25
  pid_file_dir = File.read(path)
26
26
 
27
27
  if dir.nil? || is_same_dirs(pid_file_dir, dir)
28
- if ProcessHelper.alive?(pid)
28
+ if Helper.alive?(pid)
29
29
  pid_files << PidFile.new(pid_file_dir, pid)
30
30
  else
31
31
  File.delete(path)
@@ -36,23 +36,12 @@ module Tagrity
36
36
  end
37
37
  end
38
38
 
39
- def run_dir
40
- ensure_dirs
41
- RUN_DIR
42
- end
43
-
44
39
  private
45
40
 
46
41
  def is_same_dirs(dir1, dir2)
47
42
  File.realdirpath(dir1) == File.realdirpath(dir2)
48
43
  end
49
44
 
50
- def ensure_dirs
51
- return if @ensure_dirs_done
52
- FileUtils.mkdir_p(RUN_DIR)
53
- @ensure_dirs_done = true
54
- end
55
-
56
45
  def pid_from_path(pid_file_name)
57
46
  pid_file_name.split('.')[-2].to_i
58
47
  end
@@ -76,13 +65,13 @@ module Tagrity
76
65
 
77
66
  def delete
78
67
  File.delete(pid_file_path)
79
- ProcessHelper.kill(pid.to_i)
68
+ Helper.kill(pid.to_i)
80
69
  end
81
70
 
82
71
  private
83
72
 
84
73
  def pid_file_path
85
- "#{PidFile.run_dir}/#{name}"
74
+ "#{Helper.run_dir}/#{name}"
86
75
  end
87
76
  end
88
77
  end
@@ -1,4 +1,5 @@
1
- require 'tagrity/executable_helper'
1
+ require 'tmpdir'
2
+ require 'tagrity/helper'
2
3
 
3
4
  module Tagrity
4
5
  class TagGenerator
@@ -9,37 +10,73 @@ module Tagrity
9
10
  @config = ConfigFile.instance
10
11
  end
11
12
 
13
+ def generate_all
14
+ if File.exists?(tagf)
15
+ File.delete(tagf)
16
+ end
17
+ if check_git?
18
+ files = `git ls-files 2> /dev/null`.split
19
+ else
20
+ files = `find * 2> /dev/null`.split
21
+ end
22
+ if $?.exitstatus == 0
23
+ generate(files)
24
+ else
25
+ puts "Failed to get a listing of all files under pwd for use with --fresh."
26
+ end
27
+ end
28
+
12
29
  def generate(files)
13
30
  return if files.empty?
14
31
  files
15
- .select { |file| !dont_index_file(file) && File.readable?(file) }
32
+ .select { |file| generate_tags?(file) }
16
33
  .group_by { |file| @config.ft_to_cmd(file.partition('.').last) }
17
34
  .each do |cmd, fnames|
18
- `#{cmd} -f #{tagf} --append #{fnames.join(' ')}`
19
- if $?.exitstatus != 0
20
- puts "{#{cmd}} failed to generate tags for #{fnames} into #{tagf}"
21
- else
35
+ `#{cmd} -f #{tagf} --append #{fnames.join(' ')} &> /dev/null`
36
+ if $?.exitstatus == 0
22
37
  puts "{#{cmd}} generated tags for #{fnames} into #{tagf}"
38
+ else
39
+ puts "{#{cmd}} failed to generate tags for #{fnames} into #{tagf}"
23
40
  end
24
41
  end
25
42
  end
26
43
 
27
44
  def delete_files_tags(files)
28
45
  return if files.empty?
29
- `cat #{tagf} | grep -v -F #{files.map { |f| " -e \" #{f} \""}.join(' ')} > .tagrity.tags`
30
- `mv -f .tagrity.tags #{tagf}`
31
- puts "Deleted tags for #{files} from #{tagf}"
46
+ `cat #{tagf} | grep -v -F #{files.map { |f| " -e \" #{f} \""}.join(' ')} > #{tmp_file} 2> /dev/null`
47
+ if $?.exitstatus == 0
48
+ `mv -f #{tmp_file} #{tagf}`
49
+ puts "Deleted tags for #{files} from #{tagf}"
50
+ else
51
+ puts "Failed to delete tags for #{files} from #{tagf}"
52
+ end
32
53
  end
33
54
 
34
55
  private
35
56
 
36
- def dont_index_file(fname)
57
+ def generate_tags?(file)
58
+ copacetic_with_git?(file) && indexable?(file)
59
+ end
60
+
61
+ def indexable?(file)
62
+ file != tagf && !is_file_excluded(file) && File.readable?(file)
63
+ end
64
+
65
+ def copacetic_with_git?(file)
66
+ !(check_git? && !Helper.is_file_tracked?(file))
67
+ end
68
+
69
+ def check_git?
70
+ @config.respect_git? && Helper.is_git_dir?
71
+ end
72
+
73
+ def is_file_excluded(fname)
37
74
  @config.is_ft_excluded(fname.partition('.').last) || @config.is_path_excluded(fname)
38
75
  end
39
76
 
40
77
  def assert_executables
41
78
  %w(cat grep mv).each do |exe|
42
- if !ExecutableHelper.is_executable(exe)
79
+ if !Helper.is_executable?(exe)
43
80
  raise ExecutableNonExist, "tagrity depends on the executable #{exe}"
44
81
  end
45
82
  end
@@ -48,5 +85,11 @@ module Tagrity
48
85
  def tagf
49
86
  @config.tagf
50
87
  end
88
+
89
+ def tmp_file
90
+ tmpdir = "#{Dir.tmpdir}/tagrity"
91
+ FileUtils.mkdir_p(tmpdir)
92
+ "#{tmpdir}/#{Process.pid}.tmptags"
93
+ end
51
94
  end
52
95
  end
@@ -1,3 +1,3 @@
1
1
  module Tagrity
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tagrity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam P. Regasz-Rethy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-12 00:00:00.000000000 Z
11
+ date: 2019-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -114,16 +114,16 @@ files:
114
114
  - bin/console
115
115
  - bin/setup
116
116
  - exe/tagrity
117
+ - foobar.rb
117
118
  - lib/tagrity.rb
118
119
  - lib/tagrity/cli.rb
119
120
  - lib/tagrity/commands/start.rb
120
121
  - lib/tagrity/commands/status.rb
121
122
  - lib/tagrity/commands/stop.rb
122
123
  - lib/tagrity/config_file.rb
123
- - lib/tagrity/executable_helper.rb
124
124
  - lib/tagrity/file_callbacks.rb
125
+ - lib/tagrity/helper.rb
125
126
  - lib/tagrity/pid_file.rb
126
- - lib/tagrity/process_helper.rb
127
127
  - lib/tagrity/provider.rb
128
128
  - lib/tagrity/tag_generator.rb
129
129
  - lib/tagrity/version.rb
@@ -1,9 +0,0 @@
1
- module Tagrity
2
- class ExecutableHelper
3
- class << self
4
- def is_executable(cmd)
5
- !%x{command -v #{cmd}}.empty?
6
- end
7
- end
8
- end
9
- end
@@ -1,18 +0,0 @@
1
- module Tagrity
2
- class ProcessHelper
3
- class << self
4
- def kill(pid)
5
- Process.kill('HUP', pid)
6
- end
7
-
8
- def alive?(pid)
9
- Process.kill(0, pid) # signal 0 checks if pid is alive
10
- true
11
- rescue Errno::ESRCH
12
- false
13
- rescue Errno::EPERM
14
- true
15
- end
16
- end
17
- end
18
- end