chusaku 0.1.4 → 0.2.0

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: 519cb59d3970def8c48a1f9995f8208e2455d17c6f3061ff56ceed1e9cd2e593
4
- data.tar.gz: 4de2d9aae8d0e9d97d998a53b47fd4428855ed7f5898926ae3e1f14d1b6fe90e
3
+ metadata.gz: be8c03a0fe70a6b717b8fb204ae3d2d1b9eaaa89597c7ada8c169cb49919d2ef
4
+ data.tar.gz: 28736b04b639cba7eed34695691433a0cf4defd3f48eaf7a15faced2e04540e8
5
5
  SHA512:
6
- metadata.gz: f619946e1d2a43aacec4d8bd2488d5b5af4c4e24f64bc233c294097ffc51e2c4bf3c3028530302397c026d099835d2587df1cc96356643102812bf93754a8265
7
- data.tar.gz: 871f3aab82d32b5dff9dd508fbc8119ace1125cc88e14f0e36489b094228e3843bd47fa418a0314017fe974c5ee1a149fd86585f47f494e888de92e82fa3da54
6
+ metadata.gz: 178db8776a7bfeaccbe2eea70346753cf203531c7836f706988a65c3527ac6de733580ed6e324f93658fbbeec4812fff9196f460985abdab140eea99e794ab61
7
+ data.tar.gz: f8307518e4df5d74a3c5703efed73f167138c04ae2a0d2a1f314c16bc0b1e6d101c64355d994349dc238be2a486745dbea4703389bf485dbb681412e03ae21f8
data/README.md CHANGED
@@ -49,6 +49,21 @@ From the root of your Rails application, run:
49
49
  $ bundle exec chusaku
50
50
  ```
51
51
 
52
+ Chusaku has some flags available for use as well:
53
+
54
+ ```
55
+ $ bundle exec chusaku --help
56
+ Usage: chusaku [options]
57
+ --exit-with-error-on-annotation
58
+ Fail if any file was annotated
59
+ --dry-run Run without file modifications
60
+ -v, --version Show Chusaku version number and quit
61
+ -h, --help Show this help message and quit
62
+ ```
63
+
64
+ If you'd like to use Chusaku as a Git hook, take a look at
65
+ [Lefthook](https://github.com/Arkweid/lefthook).
66
+
52
67
 
53
68
  ## Development
54
69
 
@@ -1,9 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- unless File.directory?('./app/controllers') && File.exist?('./Rakefile')
4
- abort 'Please run chusaku from the root of your project.'
5
- end
6
-
7
3
  require 'rubygems'
8
4
 
9
5
  begin
@@ -18,5 +14,6 @@ begin
18
14
  rescue StandardError
19
15
  end
20
16
 
21
- require 'chusaku'
22
- Chusaku.call
17
+ require 'chusaku/cli'
18
+
19
+ exit Chusaku::CLI.new.call
@@ -12,10 +12,14 @@ module Chusaku
12
12
  # def show
13
13
  # # ...
14
14
  # end
15
- def self.call
15
+ #
16
+ # @param {Array<String>} args - CLI flags
17
+ # @return {Integer} 0 on success, 1 on error
18
+ def self.call(args = [])
16
19
  routes = Chusaku::Routes.call
17
20
  controller_pattern = 'app/controllers/**/*_controller.rb'
18
21
  controller_paths = Dir.glob(Rails.root.join(controller_pattern))
22
+ annotated_paths = []
19
23
 
20
24
  # Loop over all controller file paths.
21
25
  controller_paths.each do |path|
@@ -26,7 +30,7 @@ module Chusaku
26
30
  # Parse the file and iterate over the parsed content, two entries at a
27
31
  # time.
28
32
  parsed_file = Chusaku::Parser.call(path: path, actions: actions.keys)
29
- parsed_file.each_cons(2) do |prev, curr|
33
+ parsed_file[:groups].each_cons(2) do |prev, curr|
30
34
  # Remove all @route comments in the previous group.
31
35
  if prev[:type] == :comment
32
36
  prev[:body] = prev[:body].gsub(/^\s*#\s*@route.*$\n/, '')
@@ -50,23 +54,33 @@ module Chusaku
50
54
  end
51
55
 
52
56
  # Write to file.
53
- parsed_content = parsed_file.map { |pf| pf[:body] }
54
- write(path, parsed_content.join)
57
+ parsed_content = parsed_file[:groups].map { |pf| pf[:body] }
58
+ new_content = parsed_content.join
59
+ if parsed_file[:content] != new_content
60
+ write(path, new_content) unless args.include?(:dry)
61
+ annotated_paths << path
62
+ end
55
63
  end
56
64
 
57
65
  # Output results to user.
58
- if controller_paths.any?
59
- puts "Annotated #{controller_paths.join(', ')}"
66
+ if annotated_paths.any?
67
+ puts "Annotated #{annotated_paths.join(', ')}"
68
+ if args.include?(:error_on_annotation)
69
+ 1
70
+ else
71
+ 0
72
+ end
60
73
  else
61
74
  puts "Nothing to annotate"
75
+ 0
62
76
  end
63
77
  end
64
78
 
65
79
  # Write given content to a file. If we're using an overridden version of File,
66
80
  # then use its method instead for testing purposes.
67
81
  #
68
- # @param {String} path
69
- # @param {String} content
82
+ # @param {String} path - File path to write to
83
+ # @param {String} content - Contents of the file
70
84
  # @return {void}
71
85
  def self.write(path, content)
72
86
  File.open(path, 'r+') do |file|
@@ -82,8 +96,8 @@ module Chusaku
82
96
  #
83
97
  # @route GET /waterlilies/:id (waterlilies)
84
98
  #
85
- # @param {Hash} action_info
86
- # @return {String}
99
+ # @param {Hash} action_info - Parsed line given by Chusaku::Parser
100
+ # @return {String} Annotation for given parsed line
87
101
  def self.annotate(action_info)
88
102
  verb = action_info[:verb]
89
103
  path = action_info[:path]
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+ require 'chusaku'
5
+
6
+ module Chusaku
7
+ class CLI
8
+ STATUS_SUCCESS = 0
9
+ STATUS_ERROR = 1
10
+
11
+ attr_reader :options
12
+
13
+ Finished = Class.new(RuntimeError)
14
+ NotARailsProject = Class.new(RuntimeError)
15
+
16
+ # Initializes a new instance of Chusaku::CLI.
17
+ #
18
+ # @return {Chusaku::CLI} Instance of this class
19
+ def initialize
20
+ @options = {}
21
+ end
22
+
23
+ # Parse CLI flags, if any, and handle applicable behaviors.
24
+ #
25
+ # @param {Array<String>} args - CLI arguments
26
+ # @return {Integer} 0 on success, 1 on error
27
+ def call(args = ARGV)
28
+ optparser.parse!(args)
29
+ check_for_rails_project
30
+ Chusaku.call(options)
31
+ rescue NotARailsProject
32
+ warn('Please run chusaku from the root of your project.')
33
+ STATUS_ERROR
34
+ rescue Finished
35
+ STATUS_SUCCESS
36
+ end
37
+
38
+ private
39
+
40
+ # Raises exception if Rails project cannot be detected.
41
+ #
42
+ # @raise {Chusaku::CLI::NotARailsProject} Exception if not Rails project
43
+ # @return {void}
44
+ def check_for_rails_project
45
+ unless File.directory?('./app/controllers') && File.exist?('./Rakefile')
46
+ raise NotARailsProject
47
+ end
48
+ end
49
+
50
+ # Returns an instance of OptionParser with supported flags.
51
+ #
52
+ # @return {OptionParser} Preconfigured OptionParser instance
53
+ def optparser
54
+ OptionParser.new do |opts|
55
+ opts.banner = 'Usage: chusaku [options]'
56
+
57
+ opts.on(
58
+ '--exit-with-error-on-annotation',
59
+ 'Fail if any file was annotated'
60
+ ) do
61
+ @options[:error_on_annotation] = true
62
+ end
63
+
64
+ opts.on(
65
+ '--dry-run',
66
+ 'Run without file modifications'
67
+ ) do
68
+ @options[:dry] = true
69
+ end
70
+
71
+ opts.on(
72
+ '-v',
73
+ '--version',
74
+ 'Show Chusaku version number and quit'
75
+ ) do
76
+ puts(Chusaku::VERSION)
77
+ raise Finished
78
+ end
79
+
80
+ opts.on(
81
+ '-h',
82
+ '--help',
83
+ 'Show this help message and quit'
84
+ ) do
85
+ puts(opts)
86
+ raise Finished
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -19,14 +19,15 @@ module Chusaku
19
19
  # body: 'end # vanilla is the best flavor\n',
20
20
  # action: nil } ]
21
21
  #
22
- # @param {String} path
23
- # @param {Array<String>} actions
24
- # @return {Array<Hash>}
22
+ # @param {String} path - File path to parse
23
+ # @param {Array<String>} actions - List of valid actions for this route
24
+ # @return {Hash} Parsed groups of the file and original content
25
25
  def self.call(path:, actions:)
26
26
  groups = []
27
27
  group = {}
28
+ content = IO.read(path)
28
29
 
29
- File.open(path, 'r').each_line do |line|
30
+ content.each_line do |line|
30
31
  parsed_line = parse_line(line: line, actions: actions)
31
32
 
32
33
  if group[:type] != parsed_line[:type]
@@ -42,7 +43,10 @@ module Chusaku
42
43
 
43
44
  # Push the last group onto the array and return.
44
45
  groups.push(group)
45
- groups
46
+ {
47
+ content: content,
48
+ groups: groups
49
+ }
46
50
  end
47
51
 
48
52
  # Given a line and actions, returns the line's type:
@@ -56,9 +60,9 @@ module Chusaku
56
60
  #
57
61
  # { type: :action, body: 'def foo', action: 'foo' }
58
62
  #
59
- # @param {String} line
60
- # @param {Array<String>} actions
61
- # @return {Hash}
63
+ # @param {String} line - A line of a file
64
+ # @param {Array<String>} actions - List of valid actions for this route
65
+ # @return {Hash} Parsed line
62
66
  def self.parse_line(line:, actions:)
63
67
  comment_match = /^\s*#.*$/.match(line)
64
68
  def_match = /^\s*def\s+(\w*)\s*\w*.*$/.match(line)
@@ -9,11 +9,10 @@ module Chusaku
9
9
  # {
10
10
  # 'users' => {
11
11
  # 'edit' => [
12
- # { verb: ['GET'], path: '/users/:id', name: ['edit_user'] }],
12
+ # { verb: 'GET', path: '/users/:id', name: 'edit_user' }],
13
13
  # 'update' => [
14
- # { verb: ['PUT', 'PATCH'],
15
- # path: '/users',
16
- # name: ['edit_user', 'edit_user2'] }]
14
+ # { verb: 'PATCH', path: '/users', name: 'edit_user' },
15
+ # { verb: 'PUT', path: '/users', name: 'edit_user' }]
17
16
  # },
18
17
  # 'empanadas' => {
19
18
  # 'create' => [
@@ -61,7 +60,7 @@ module Chusaku
61
60
  paths = {}
62
61
 
63
62
  routes.each do |_controller, actions|
64
- actions.each do |action, data|
63
+ actions.each do |_action, data|
65
64
  data.each do |datum|
66
65
  paths[datum[:path]] ||= datum[:name]
67
66
  datum[:name] ||= paths[datum[:path]]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chusaku
4
- VERSION = '0.1.4'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chusaku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nishiki Liu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-05 00:00:00.000000000 Z
11
+ date: 2019-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,6 +86,7 @@ files:
86
86
  - bin/setup
87
87
  - chusaku.gemspec
88
88
  - lib/chusaku.rb
89
+ - lib/chusaku/cli.rb
89
90
  - lib/chusaku/parser.rb
90
91
  - lib/chusaku/routes.rb
91
92
  - lib/chusaku/version.rb