gemfile_arranger 0.0.1

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 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