gemfile_arranger 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 43ebe801a6d26a0a473e3ac5dacdfa6a6e85557c
4
+ data.tar.gz: 94696ef5d4040db27c90457aaf44b2fcb986637e
5
+ SHA512:
6
+ metadata.gz: 1de3a0dd30b33be2f3fb8e3d9e4670c20147cd2fb780ff1ed7d26515ccaf43475b02c82185bb402a9db32715e1dc0a81970e845c9f4160589a5ef68156ba8d13
7
+ data.tar.gz: 2a39f863a6abc96126f90413ffb74c41e8321636067ce4341527bf38fa793061dc0f6e4115afbbb8374360fd5d53518cbdc3b18dfb0f24d35cce5b550469532c
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.hound.yml ADDED
@@ -0,0 +1,3 @@
1
+ ruby:
2
+ enabled: true
3
+ config_file: .rubocop.yml
data/.rubocop-todo.yml ADDED
@@ -0,0 +1,9 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`.
2
+ # The point is for the user to remove these configuration records
3
+ # one by one as the offences are removed from the code base.
4
+
5
+ Blocks:
6
+ Enabled: false
7
+
8
+ LineLength:
9
+ Enabled: false
data/.rubocop.yml ADDED
@@ -0,0 +1,12 @@
1
+ inherit_from: .rubocop-todo.yml
2
+ AllCops:
3
+ Include:
4
+ - '**/Rakefile'
5
+ - Gemfile
6
+ - gemfile_arranger.gemspec
7
+ - bin/**
8
+ - lib/**/*.rake
9
+ Exclude:
10
+ - pkg/**
11
+ StringLiterals:
12
+ EnforcedStyle: single_quotes
data/.tachikoma.yml ADDED
@@ -0,0 +1 @@
1
+ strategy: 'none'
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9
4
+ - 2.0
5
+ - 2.1
6
+ before_install:
7
+ - gem update bundler
8
+ notifications:
9
+ email:
10
+ - ogataken@gmail.com
11
+ branches:
12
+ only:
13
+ - master
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gemfile_arranger.gemspec
4
+ gemspec
5
+
6
+ gem 'byebug' if RUBY_VERSION >= '2'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 sanemat
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # GemfileArranger
2
+
3
+ [![Gem Version](http://img.shields.io/gem/v/gemfile_arranger.svg?style=flat)](http://badge.fury.io/rb/gemfile_arranger)
4
+ [![Build Status](http://img.shields.io/travis/sanemat/gemfile_arranger/master.svg?style=flat)](https://travis-ci.org/sanemat/gemfile_arranger)
5
+ [![Code Climate](http://img.shields.io/codeclimate/github/sanemat/gemfile_arranger.svg?style=flat)](https://codeclimate.com/github/sanemat/gemfile_arranger)
6
+ [![Coverage Status](http://img.shields.io/coveralls/sanemat/gemfile_arranger/master.svg?style=flat)](https://coveralls.io/r/sanemat/gemfile_arranger)
7
+
8
+
9
+ TODO: Write a gem description
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'gemfile_arranger'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install gemfile_arranger
26
+
27
+ ## Usage
28
+
29
+ TODO: Write usage instructions here
30
+
31
+ ## Contributing
32
+
33
+ 1. Fork it ( https://github.com/sanemat/gemfile_arranger/fork )
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
35
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
36
+ 4. Push to the branch (`git push origin my-new-feature`)
37
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.verbose = true
6
+ end
7
+
8
+ task default: :test
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gemfile_arranger'
4
+ require 'gemfile_arranger/cli'
5
+
6
+ GemfileArranger::CLI.start(ARGV)
@@ -0,0 +1,12 @@
1
+ block_order:
2
+ - source
3
+ - ruby
4
+ - gemspec
5
+ - gem
6
+ - group
7
+ group:
8
+ - production
9
+ - staging
10
+ - development
11
+ - test
12
+ priority_gem:
data/example.txt ADDED
@@ -0,0 +1,41 @@
1
+ yaml setting(idea: .gemfile_arranger.yml)
2
+
3
+ block_order:
4
+ - source
5
+ - ruby
6
+ - gemspec
7
+ - gem
8
+ - group
9
+ group:
10
+ - production
11
+ - staging
12
+ - development
13
+ - test
14
+ priority_gem:
15
+ - rails
16
+ - redis
17
+
18
+ idobata rule:
19
+ https://gist.github.com/kakutani/43b9f42197ab002fcdf8
20
+
21
+ examples:
22
+ - examples/idobata.io.Gemfile
23
+ - examples/pigeon.tachikoma.io.Gemfile
24
+
25
+ ## 説明
26
+
27
+ 1. どのブロックなのかがわかる
28
+ 2. ブロックごとに並べる
29
+ 3. ブロックの中で、
30
+
31
+ - [x] sourceを一番上のグループ、rubyを二番目のグループ, gemspecを三番目, gemを四番目, groupを五番目に並べる
32
+ - groupの並び順設定通りに並べる
33
+ - groupの並び順設定がなければ、sortの設定で、groupを並べる
34
+ - [x] priority_gem設定があり、各group内でpriority_gemがあったら、まずその順番に並べる
35
+ - 3番目のグループから、sortの設定で、gemを並べ替える
36
+
37
+ ## 懸念
38
+
39
+ - 裸のgemにgroupがついていたら?? -> { group: :development } がつくだけなので注意
40
+ - Bundler::Dsl にpublicで定義されたメソッドしか使えない ホワイトリストで良さそう(ただし動的に作る)
41
+ - dog-fooding
@@ -0,0 +1,100 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '2.1.2'
4
+
5
+ gem 'action_args'
6
+ gem 'actionpack-xml_parser'
7
+ gem 'actionview-encoded_mail_to'
8
+ gem 'active_attr'
9
+ gem 'active_model_serializers', github: 'ursm/active_model_serializers', branch: 'rails-4.1'
10
+ gem 'bootstrap-sass', '~> 2.3' # TODO 3.x に上げる
11
+ gem 'carrierwave'
12
+ gem 'carrierwave_backgrounder'
13
+ gem 'cells'
14
+ gem 'chronic'
15
+ gem 'closure-compiler'
16
+ gem 'coffee-rails', '~> 4.0.0'
17
+ gem 'custom_configuration'
18
+ gem 'devise'
19
+ gem 'devise-async'
20
+ gem 'ember-data-source', '0.14'
21
+ gem 'ember-rails'
22
+ gem 'enumerize', github: 'ursm/enumerize', branch: 'fix-ar4'
23
+ gem 'escape_utils'
24
+ gem 'event_tracker'
25
+ gem 'figaro'
26
+ gem 'fog'
27
+ gem 'font-awesome-rails'
28
+ gem 'gcm'
29
+ gem 'gemoji'
30
+ gem 'girl_friday'
31
+ gem 'github-linguist', group: 'has-icu'
32
+ gem 'github-markdown'
33
+ gem 'grocer'
34
+ gem 'haml-rails'
35
+ gem 'hamlbars'
36
+ gem 'hashie'
37
+ gem 'hiredis'
38
+ gem 'hpricot'
39
+ gem 'html-pipeline', require: 'html/pipeline', github: 'jch/html-pipeline'
40
+ gem 'jquery-atwho-rails', '0.4.7' # 0.4.9 は補完が妙高さんになる
41
+ gem 'jquery-rails'
42
+ gem 'jquery-ui-rails'
43
+ gem 'mini_magick'
44
+ gem 'momentjs-rails'
45
+ gem 'oj'
46
+ gem 'omniauth'
47
+ gem 'omniauth-github'
48
+ gem 'party_foul', github: 'tricknotes/party_foul', branch: 'fix-issue-labels-format' # Workaround until this PR is merged: https://github.com/dockyard/party_foul/pull/103
49
+ gem 'pg'
50
+ gem 'pusher'
51
+ gem 'rails', '~> 4.1.0'
52
+ gem 'redcarpet'
53
+ gem 'redis', require: %w(redis redis/connection/hiredis)
54
+ gem 'redis-objects', require: 'redis/objects'
55
+ gem 'retriable'
56
+ gem 'rinku'
57
+ gem 'sanitize'
58
+ gem 'sass-rails', '~> 4.0.0'
59
+ gem 'sidekiq'
60
+ gem 'sinatra', require: false # Sidekiq::Web, GirlFriday::Server
61
+ gem 'skylight'
62
+ gem 'uglifier', '>= 1.3.0'
63
+ gem 'underscore-rails'
64
+ gem 'unf'
65
+ gem 'unicorn'
66
+ gem 'visibilityjs'
67
+
68
+ group :development do
69
+ gem 'bullet'
70
+ gem 'letter_opener'
71
+ gem 'pry', group: 'test'
72
+ gem 'quiet_assets'
73
+ gem 'tapp-awesome_print', group: 'test'
74
+ gem 'vendorer'
75
+ gem 'what_methods'
76
+ end
77
+
78
+ group :test do
79
+ gem 'capybara', github: 'jnicklas/capybara'
80
+ gem 'capybara-webkit'
81
+ gem 'database_rewinder'
82
+ gem 'email_spec', github: 'bmabey/email-spec'
83
+ gem 'factory_girl_rails', group: 'development'
84
+ gem 'fakeredis', require: 'fakeredis/rspec', github: 'guilleiguaran/fakeredis'
85
+ gem 'fuubar', '~> 2.0.0.beta'
86
+ gem 'launchy'
87
+ gem 'rspec-cells'
88
+ gem 'rspec-its'
89
+ gem 'rspec-rails', '~> 3.0.0.beta', group: 'development'
90
+ gem 'rspec-retry' # TravisCI上でどうしてもタイミング依存でfailするcapybara経由のexampleがあるので止むなし
91
+ gem 'teaspoon', group: 'development'
92
+ end
93
+
94
+ group :production do
95
+ gem 'dalli'
96
+ gem 'newrelic-redis'
97
+ gem 'newrelic_rpm'
98
+ gem 'rails_12factor', require: false
99
+ gem 'memcachier', require: false
100
+ end
@@ -0,0 +1,86 @@
1
+ source 'https://rubygems.org'
2
+ # For heroku
3
+ ruby '2.1.3'
4
+
5
+ # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
6
+ gem 'rails', github: 'rails/rails', branch: '4-1-stable'
7
+ # Use postgresql as the database for Active Record
8
+ gem 'pg'
9
+ # Use SCSS for stylesheets
10
+ gem 'sass-rails', '< 5.0.0'
11
+ gem 'sprockets'
12
+ # Use Uglifier as compressor for JavaScript assets
13
+ gem 'uglifier', '>= 1.3.0'
14
+ # Use CoffeeScript for .js.coffee assets and views
15
+ gem 'coffee-rails'
16
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
17
+ # gem 'therubyracer', platforms: :ruby
18
+
19
+ # Use jquery as the JavaScript library
20
+ gem 'jquery-rails'
21
+
22
+ gem 'angularjs-rails'
23
+ gem 'font-awesome-rails'
24
+ gem 'haml-rails'
25
+ gem 'newrelic_rpm'
26
+ gem 'octokit'
27
+ gem 'faraday-http-cache'
28
+ gem 'omniauth-github'
29
+ gem 'que'
30
+ gem 'sentry-raven'
31
+ gem 'multi_json'
32
+ gem 'oj'
33
+
34
+ gem 'bourbon'
35
+ gem 'neat'
36
+ gem 'normalize-rails'
37
+
38
+ gem 'docker-api', require: 'docker'
39
+
40
+ gem 'base32'
41
+ gem 'safe_yaml'
42
+ gem 'druuid'
43
+
44
+ group :staging, :production do
45
+ gem 'rails_12factor'
46
+ gem 'unicorn'
47
+ end
48
+
49
+ group :development, :test do
50
+ gem 'byebug'
51
+ gem 'pry'
52
+ gem 'pry-rails'
53
+ gem 'rspec-rails'
54
+ gem 'dotenv-rails'
55
+ end
56
+
57
+ group :test do
58
+ gem 'capybara'
59
+ gem 'capybara-webkit'
60
+ gem 'database_rewinder'
61
+ gem 'factory_girl_rails'
62
+ gem 'launchy'
63
+ gem 'webmock'
64
+ gem 'shoulda-matchers'
65
+ gem 'timecop'
66
+ gem 'nokogiri'
67
+ end
68
+
69
+ group :development do
70
+ gem 'spring'
71
+ gem 'railroady'
72
+ end
73
+
74
+ # Use ActiveModel has_secure_password
75
+ # gem 'bcrypt', '~> 3.1.7'
76
+
77
+ # Use unicorn as the app server
78
+ # gem 'unicorn'
79
+
80
+ # Use Capistrano for deployment
81
+ # gem 'capistrano-rails', group: :development
82
+
83
+ # Use debugger
84
+ # gem 'debugger', group: [:development, :test]
85
+
86
+ # gem 'grouped', group: :development
@@ -0,0 +1,18 @@
1
+ gem 'action_args'
2
+ source 'https://rubygems.org'
3
+
4
+ group :development do
5
+ gem 'bullet'
6
+ end
7
+
8
+ ruby '2.1.2'
9
+ gemspec
10
+
11
+ platforms :ruby do
12
+ gem 'mami'
13
+ end
14
+
15
+ group :test do
16
+ gem 'database_rewinder'
17
+ gem 'capybara-webkit'
18
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gemfile_arranger/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'gemfile_arranger'
8
+ spec.version = GemfileArranger::VERSION
9
+ spec.authors = ['sanemat']
10
+ spec.email = ['o.gata.ken@gmail.com']
11
+ spec.summary = 'A Gemfile file scrubber for the truly insane.'
12
+ spec.description = 'Sort gems, fix indent, etc.'
13
+ spec.homepage = 'https://github.com/sanemat/gemfile_arranger'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'parser', '~> 2.2.0.pre.8'
22
+ spec.add_dependency 'unparser'
23
+ spec.add_dependency 'safe_yaml'
24
+ spec.add_dependency 'thor'
25
+ spec.add_development_dependency 'unindent'
26
+ spec.add_development_dependency 'bundler', '~> 1.7'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'test-unit'
29
+ end
@@ -0,0 +1,7 @@
1
+ require 'parser/current'
2
+
3
+ module GemfileArranger
4
+ require 'gemfile_arranger/traverse/sort_block'
5
+ require 'gemfile_arranger/traverse/sort_gems_in_group'
6
+ require 'gemfile_arranger/traverse/sort_priority_gems_in_group'
7
+ end
@@ -0,0 +1,126 @@
1
+ require 'gemfile_arranger'
2
+ require 'gemfile_arranger/version'
3
+ require 'thor'
4
+ require 'safe_yaml/load'
5
+ require 'unparser'
6
+ require 'pathname'
7
+
8
+ module GemfileArranger
9
+ class InitConfig < Thor::Group
10
+ include Thor::Actions
11
+ SHORT_DESCRIPTION = 'Generate a simple .gemfile_arranger.yml, placed in the current directory'
12
+
13
+ def self.source_root
14
+ Pathname
15
+ .new(__FILE__)
16
+ .dirname
17
+ .join('templates')
18
+ .expand_path
19
+ end
20
+
21
+ def create_gemfile_arranger_yml
22
+ copy_file '.gemfile_arranger.yml'
23
+ end
24
+ end
25
+
26
+ class CLI < Thor
27
+ default_task :arrange
28
+
29
+ desc 'version', "Print the gemfile_arranger's version information"
30
+ def version
31
+ puts "Gemfile Arranger version #{VERSION}"
32
+ end
33
+ map %w(-v --version) => :version
34
+
35
+ desc 'arrange', 'Arrange given Gemfile'
36
+ option :gemfile, default: 'Gemfile', desc: 'The location of the Gemfile(5)'
37
+ option :auto_correct, type: :boolean, aliases: '-a', desc: 'Auto-correct Gemfile(5)'
38
+ def arrange
39
+ code = gemfile_contents(options[:gemfile])
40
+
41
+ buffer = Parser::Source::Buffer.new('(gemfile_arranger arrange)')
42
+ buffer.source = code
43
+ parser = Parser::CurrentRuby.new
44
+ ast = parser.parse(buffer)
45
+
46
+ sort_gems_in_group = Traverse::SortGemsInGroup.new
47
+ rewrited_ast = sort_gems_in_group.process(ast)
48
+
49
+ sort_priority_gems_in_group = Traverse::SortPriorityGemsInGroup.new(config['priority_gem'])
50
+ rewrited_ast = sort_priority_gems_in_group.process(rewrited_ast)
51
+
52
+ sort_block = Traverse::SortBlock.new(config['block_order'])
53
+ rewrited_ast = sort_block.process(rewrited_ast)
54
+
55
+ rewrited_gemfile = Unparser.unparse(rewrited_ast)
56
+ if options[:auto_correct]
57
+ rewrite_gemfile(rewrited_gemfile, options[:gemfile])
58
+ puts "Rewrite Gemfile compete! #{options[:gemfile]}"
59
+ else
60
+ puts rewrited_gemfile
61
+ end
62
+ end
63
+
64
+ desc 'show-config', 'Print applying configuration'
65
+ def show_config
66
+ puts config
67
+ end
68
+
69
+ desc 'show-base-config', 'Print original base configuration'
70
+ def show_base_config
71
+ puts base_config
72
+ end
73
+
74
+ register(InitConfig, 'init', 'init', InitConfig::SHORT_DESCRIPTION)
75
+
76
+ private
77
+
78
+ def base_config
79
+ base_config_path = file_path
80
+ .dirname
81
+ .join('..', '..', 'config', '.gemfile_arranger.base.yml')
82
+ .expand_path
83
+ fail "Can not read base config: #{base_config_path}" unless base_config_path.file?
84
+
85
+ base_config_contents = base_config_path.read
86
+ SafeYAML.load(base_config_contents) || {}
87
+ end
88
+
89
+ def user_config
90
+ user_config_path = root_path
91
+ .join('.gemfile_arranger.yml')
92
+ .expand_path
93
+ return {} unless user_config_path.file?
94
+
95
+ user_config_contents = user_config_path.read
96
+ SafeYAML.load(user_config_contents) || {}
97
+ end
98
+
99
+ def config
100
+ base_config.merge(user_config)
101
+ end
102
+
103
+ def gemfile_contents(filename)
104
+ gemfile_path = root_path
105
+ .join(filename)
106
+ .expand_path
107
+ fail "Can not read Gemfile: #{gemfile_path}" unless gemfile_path.file?
108
+ gemfile_path.read
109
+ end
110
+
111
+ def root_path
112
+ Pathname.pwd
113
+ end
114
+
115
+ def file_path
116
+ Pathname.new(__FILE__)
117
+ end
118
+
119
+ def rewrite_gemfile(contents, filename)
120
+ root_path
121
+ .join(filename)
122
+ .expand_path
123
+ .write(contents + "\n")
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,15 @@
1
+ # Edit your configuration for gemfile_arranger
2
+ #block_order:
3
+ # - source
4
+ # - ruby
5
+ # - gemspec
6
+ # - gem
7
+ # - group
8
+ #group:
9
+ # - production
10
+ # - staging
11
+ # - development
12
+ # - test
13
+ #priority_gem:
14
+ # - rails
15
+ # - redis
@@ -0,0 +1,13 @@
1
+ module GemfileArranger
2
+ module Testing
3
+ # NOTE: Too slow(140X slower).
4
+ # ast: 0.00487 seconds
5
+ # contents: 0.678528 seconds
6
+ def contents_to_ast(contents)
7
+ buffer = Parser::Source::Buffer.new('(contents_to_ast)')
8
+ buffer.source = contents
9
+ parser = Parser::CurrentRuby.new
10
+ parser.parse(buffer)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ module GemfileArranger
2
+ module Traverse
3
+ class SortBlock < Parser::AST::Processor
4
+ def initialize(keys)
5
+ @keys = Array(keys).dup.map(&:to_sym)
6
+ end
7
+
8
+ def on_begin(node)
9
+ sorted_block = sort_block_with_keys(node, @keys)
10
+ node.updated(:begin, sorted_block) if node != sorted_block
11
+ end
12
+
13
+ def sort_block_with_keys(node, keys)
14
+ node.children.sort_by.with_index do |child, i|
15
+ _, gem_name, *_ = child.children
16
+ key_index = keys.index(gem_name) || keys.length
17
+ [key_index, i]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module GemfileArranger
2
+ module Traverse
3
+ class SortGemsInGroup < Parser::AST::Processor
4
+ def on_block(node)
5
+ sorted_block = sort_gems_in_group(node)
6
+ node.updated(:block, sorted_block) if node != sorted_block
7
+ end
8
+
9
+ def sort_gems_in_group(node)
10
+ send_node, args_node, body_node = node.children
11
+
12
+ return node if send_node.children[1] != :group
13
+ return node if body_node.type != :begin
14
+ gems = body_node.children.sort_by.with_index do |child, i|
15
+ gem_name = child.children[2].children[0]
16
+ [gem_name, i]
17
+ end
18
+ return node if body_node.children == gems
19
+
20
+ sorted_body_node = body_node.updated(:begin, gems)
21
+ [send_node, args_node, sorted_body_node]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ module GemfileArranger
2
+ module Traverse
3
+ class SortPriorityGemsInGroup < Parser::AST::Processor
4
+ def initialize(keys)
5
+ @keys = Array(keys).dup.map(&:to_s)
6
+ end
7
+
8
+ def on_block(node)
9
+ sorted_block = sort_gems_in_group_with_keys(node, @keys)
10
+ node.updated(:block, sorted_block) if node != sorted_block
11
+ end
12
+
13
+ def sort_gems_in_group_with_keys(node, keys)
14
+ send_node, args_node, body_node = node.children
15
+ return node if send_node.children[1] != :group
16
+ return node if body_node.type != :begin
17
+ gems = body_node.children.sort_by.with_index do |child, i|
18
+ gem_name = child.children[2].children[0]
19
+ key_index = keys.index(gem_name) || keys.length
20
+ [key_index, i]
21
+ end
22
+ return node if body_node.children == gems
23
+
24
+ sorted_body_node = body_node.updated(:begin, gems)
25
+ [send_node, args_node, sorted_body_node]
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module GemfileArranger
2
+ VERSION = '0.0.1'
3
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+ require 'unindent'
3
+ require 'gemfile_arranger'
4
+ require 'gemfile_arranger/testing'
@@ -0,0 +1,29 @@
1
+ require_relative 'helper'
2
+
3
+ class TestingTest < Test::Unit::TestCase
4
+ include AST::Sexp
5
+ include GemfileArranger::Testing
6
+
7
+ test 'Equal contents_to_ast' do
8
+ contents = <<-EOS.unindent
9
+ gem 'bar'
10
+ gem 'action_args'
11
+ source 'https://rubygems.org'
12
+ ruby '2.1.5'
13
+ EOS
14
+ ast = \
15
+ s(:begin,
16
+ s(:send, nil, :gem,
17
+ s(:str, 'bar')),
18
+ s(:send, nil, :gem,
19
+ s(:str, 'action_args')),
20
+ s(:send, nil, :source,
21
+ s(:str, 'https://rubygems.org')),
22
+ s(:send, nil, :ruby,
23
+ s(:str, '2.1.5')))
24
+
25
+ assert do
26
+ contents_to_ast(contents) == ast
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,72 @@
1
+ require_relative 'helper'
2
+
3
+ class TraverseSortBlockTest < Test::Unit::TestCase
4
+ include AST::Sexp
5
+ include GemfileArranger::Testing
6
+
7
+ test 'Sort by large categories' do
8
+ # ----
9
+ # gem 'bar'
10
+ # gem 'action_args'
11
+ # source 'https://rubygems.org'
12
+ # ruby '2.1.5'
13
+ # ----
14
+ ast = \
15
+ s(:begin,
16
+ s(:send, nil, :gem,
17
+ s(:str, 'bar')),
18
+ s(:send, nil, :gem,
19
+ s(:str, 'action_args')),
20
+ s(:send, nil, :source,
21
+ s(:str, 'https://rubygems.org')),
22
+ s(:send, nil, :ruby,
23
+ s(:str, '2.1.5')))
24
+
25
+ # ----
26
+ # source 'https://rubygems.org'
27
+ # ruby '2.1.5'
28
+ # gem 'bar'
29
+ # gem 'action_args'
30
+ # ----
31
+ ast_expected = \
32
+ s(:begin,
33
+ s(:send, nil, :source,
34
+ s(:str, 'https://rubygems.org')),
35
+ s(:send, nil, :ruby,
36
+ s(:str, '2.1.5')),
37
+ s(:send, nil, :gem,
38
+ s(:str, 'bar')),
39
+ s(:send, nil, :gem,
40
+ s(:str, 'action_args')))
41
+
42
+ block_order = %w(source ruby gemspec gem group)
43
+ sort_block = GemfileArranger::Traverse::SortBlock.new(block_order)
44
+
45
+ assert do
46
+ sort_block.process(ast) == ast_expected
47
+ end
48
+ end
49
+
50
+ test 'Sort by large categories with contents' do
51
+ contents = <<-EOS.unindent
52
+ gem 'bar'
53
+ gem 'action_args'
54
+ source 'https://rubygems.org'
55
+ ruby '2.1.5'
56
+ EOS
57
+
58
+ expected = <<-EOS.unindent
59
+ source 'https://rubygems.org'
60
+ ruby '2.1.5'
61
+ gem 'bar'
62
+ gem 'action_args'
63
+ EOS
64
+
65
+ block_order = %w(source ruby gemspec gem group)
66
+ sort_block = GemfileArranger::Traverse::SortBlock.new(block_order)
67
+
68
+ assert do
69
+ sort_block.process(contents_to_ast(contents)) == contents_to_ast(expected)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,60 @@
1
+ require_relative 'helper'
2
+
3
+ class TraverseSorGemsInGroupTest < Test::Unit::TestCase
4
+ include AST::Sexp
5
+ include GemfileArranger::Testing
6
+
7
+ test 'Sort gems in group with contents' do
8
+ contents = <<-EOS.unindent
9
+ gem 'bar'
10
+ source 'https://rubygems.org'
11
+ group :development do
12
+ gem 'foo'
13
+ gem 'baz'
14
+ end
15
+ ruby '2.1.5'
16
+ EOS
17
+
18
+ expected = <<-EOS.unindent
19
+ gem 'bar'
20
+ source 'https://rubygems.org'
21
+ group :development do
22
+ gem 'baz'
23
+ gem 'foo'
24
+ end
25
+ ruby '2.1.5'
26
+ EOS
27
+
28
+ sort_block = GemfileArranger::Traverse::SortGemsInGroup.new
29
+
30
+ assert do
31
+ sort_block.process(contents_to_ast(contents)) == contents_to_ast(expected)
32
+ end
33
+ end
34
+
35
+ test 'No effect to single gem in group' do
36
+ contents = <<-EOS.unindent
37
+ gem 'bar'
38
+ source 'https://rubygems.org'
39
+ group :development do
40
+ gem 'single'
41
+ end
42
+ ruby '2.1.5'
43
+ EOS
44
+
45
+ expected = <<-EOS.unindent
46
+ gem 'bar'
47
+ source 'https://rubygems.org'
48
+ group :development do
49
+ gem 'single'
50
+ end
51
+ ruby '2.1.5'
52
+ EOS
53
+
54
+ sort_block = GemfileArranger::Traverse::SortGemsInGroup.new
55
+
56
+ assert do
57
+ sort_block.process(contents_to_ast(contents)) == contents_to_ast(expected)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'helper'
2
+
3
+ class TraverseSorPriorityGemsInGroupTest < Test::Unit::TestCase
4
+ include AST::Sexp
5
+ include GemfileArranger::Testing
6
+
7
+ test 'Sort priority gems in group with contents' do
8
+ contents = <<-EOS.unindent
9
+ gem 'bar'
10
+ source 'https://rubygems.org'
11
+ group :development do
12
+ gem 'foo'
13
+ gem 'priority-2nd'
14
+ gem 'priority-1st'
15
+ gem 'baz'
16
+ end
17
+ ruby '2.1.5'
18
+ EOS
19
+
20
+ expected = <<-EOS.unindent
21
+ gem 'bar'
22
+ source 'https://rubygems.org'
23
+ group :development do
24
+ gem 'priority-1st'
25
+ gem 'priority-2nd'
26
+ gem 'foo'
27
+ gem 'baz'
28
+ end
29
+ ruby '2.1.5'
30
+ EOS
31
+ priority_gems = %w(priority-1st priority-2nd)
32
+
33
+ sort_block = GemfileArranger::Traverse::SortPriorityGemsInGroup.new(priority_gems)
34
+
35
+ assert do
36
+ sort_block.process(contents_to_ast(contents)) == contents_to_ast(expected)
37
+ end
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gemfile_arranger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - sanemat
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.0.pre.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.0.pre.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: unparser
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: safe_yaml
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: unindent
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.7'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.7'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: test-unit
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Sort gems, fix indent, etc.
126
+ email:
127
+ - o.gata.ken@gmail.com
128
+ executables:
129
+ - gemfile_arrange
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".gitignore"
134
+ - ".hound.yml"
135
+ - ".rubocop-todo.yml"
136
+ - ".rubocop.yml"
137
+ - ".tachikoma.yml"
138
+ - ".travis.yml"
139
+ - Gemfile
140
+ - LICENSE.txt
141
+ - README.md
142
+ - Rakefile
143
+ - bin/gemfile_arrange
144
+ - config/.gemfile_arranger.base.yml
145
+ - example.txt
146
+ - examples/idobata.io.Gemfile
147
+ - examples/pigeon.tachikoma.io.Gemfile
148
+ - examples/sort-example.Gemfile
149
+ - gemfile_arranger.gemspec
150
+ - lib/gemfile_arranger.rb
151
+ - lib/gemfile_arranger/cli.rb
152
+ - lib/gemfile_arranger/templates/.gemfile_arranger.yml
153
+ - lib/gemfile_arranger/testing.rb
154
+ - lib/gemfile_arranger/traverse/sort_block.rb
155
+ - lib/gemfile_arranger/traverse/sort_gems_in_group.rb
156
+ - lib/gemfile_arranger/traverse/sort_priority_gems_in_group.rb
157
+ - lib/gemfile_arranger/version.rb
158
+ - test/helper.rb
159
+ - test/test_testing.rb
160
+ - test/test_traverse_sort_block.rb
161
+ - test/test_traverse_sort_gems_in_group.rb
162
+ - test/test_traverse_sort_priority_gems_in_group.rb
163
+ homepage: https://github.com/sanemat/gemfile_arranger
164
+ licenses:
165
+ - MIT
166
+ metadata: {}
167
+ post_install_message:
168
+ rdoc_options: []
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ requirements: []
182
+ rubyforge_project:
183
+ rubygems_version: 2.2.2
184
+ signing_key:
185
+ specification_version: 4
186
+ summary: A Gemfile file scrubber for the truly insane.
187
+ test_files:
188
+ - test/helper.rb
189
+ - test/test_testing.rb
190
+ - test/test_traverse_sort_block.rb
191
+ - test/test_traverse_sort_gems_in_group.rb
192
+ - test/test_traverse_sort_priority_gems_in_group.rb