tagrity 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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