This repository was archived by the owner on Apr 14, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2k
[Feature] bundle canonical #6623
Closed
Closed
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
ae7a913
Add basic skeleton for bundle canonical
agrim123 27d1776
Add --view option and related specs
agrim123 1881878
Use hash rocket syntax
agrim123 498f4bd
Extract gem contents function to make it reusable
agrim123 71b2267
Extract deps contents function
agrim123 188e4ff
Move gemfile logic to Gemfile class
agrim123 a4c6e98
Add specs for Gemfile class
agrim123 43bb94f
Add as_string option
agrim123 7087fe2
Update gemfile specs
agrim123 456d868
Add documentation
agrim123 ed51bf6
Fix inline groups and specs
agrim123 79dbf34
Make test verbose
agrim123 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Bundler | ||
| class CLI::Canonical | ||
| def initialize(options) | ||
| @options = options | ||
| end | ||
|
|
||
| def run | ||
| contents = Gemfile.full_gemfile(:show_summary => true, :as_string => true) | ||
|
|
||
| if @options[:view] | ||
| puts contents | ||
| else | ||
| SharedHelpers.write_to_gemfile(Bundler.default_gemfile, contents) | ||
| end | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Bundler | ||
| class Gemfile | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this class definitely should be named something different
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think |
||
| def self.full_gemfile(options = {}) | ||
| gemfile = new(options) | ||
| gemfile.full_gemfile | ||
| end | ||
|
|
||
| def initialize(options = {}) | ||
| @options = options | ||
| @resolve = nil | ||
| end | ||
|
|
||
| def full_gemfile | ||
| definition = Bundler.definition | ||
| @resolve = definition.resolve if @options[:show_summary] | ||
|
|
||
| gemfile = [] | ||
| Array(definition.send(:sources).global_rubygems_source).each do |s| | ||
| s.remotes.each {|r| gemfile << "source #{r.to_s.dump}" } | ||
| end | ||
|
|
||
| gemfile << nil | ||
|
|
||
| definition.dependencies.group_by(&:groups).each_key(&:sort!).sort_by(&:first).each do |groups, deps| | ||
| gemfile << groups_wise(deps, groups) | ||
| end | ||
|
|
||
| if @options[:as_string] | ||
| gemfile.join("\n").gsub(/\n{3,}/, "\n\n").strip | ||
| else | ||
| gemfile | ||
| end | ||
| end | ||
|
|
||
| # @param [Bundler::Dependency] dep Dependency instance of the gem | ||
| # @param [Boolean] show_groups Whether groups be shown in gem contents | ||
| # @return [[String]] | ||
| def gem_contents(dep, show_groups = false) | ||
| contents = [] | ||
| contents << "gem " << dep.name.dump | ||
|
|
||
| contents << ", " << dep.requirement.as_list.map(&:inspect).join(", ") unless dep.requirement.none? | ||
|
|
||
| if show_groups || @options[:inline_groups] | ||
| groups = dep.groups.reject {|g| g.to_s == "default" }.uniq | ||
|
|
||
| unless groups.empty? | ||
| contents << if groups.size == 1 | ||
| ", :group => :#{groups[0]}" | ||
| else | ||
| ", :groups => #{groups.inspect}" | ||
| end | ||
| end | ||
| end | ||
|
|
||
| contents << ", :source => \"" << dep.source.remotes << "\"" unless dep.source.nil? | ||
| # contents = ["gemspec"] if @dep.source.options["gemspec"] | ||
|
|
||
| contents << ", :platforms => " << dep.platforms.inspect unless dep.platforms.empty? | ||
|
|
||
| env = dep.instance_variable_get(:@env) | ||
| contents << ", :env => " << env.inspect if env | ||
|
|
||
| if (req = dep.autorequire) && !req.empty? | ||
| req = req.first if req.size == 1 | ||
| contents << ", :require => " << req.inspect | ||
| end | ||
|
|
||
| contents | ||
| end | ||
|
|
||
| def groups_wise(deps, groups) | ||
| gemfile = [] | ||
| groups = nil if groups.empty? || groups.include?(:default) | ||
|
|
||
| group_block = groups && !@options[:inline_groups] | ||
| inside_group = !groups.nil? && !@options[:inline_groups] | ||
| gemfile << "group #{groups.map(&:inspect).uniq.join(", ")} do" if group_block | ||
| gemfile << deps_contents(deps.sort_by(&:name), inside_group) | ||
| gemfile << "end" if group_block | ||
| gemfile << nil | ||
|
|
||
| gemfile | ||
| end | ||
|
|
||
| private | ||
|
|
||
| # @param [[Bundler::Dependency]] deps Array of dependency instances of gems | ||
| # @param [Boolean] inside_group Whether gems to be shown are inside group | ||
| # @return [[String]] | ||
| def deps_contents(deps, inside_group = false) | ||
| contents = [] | ||
| deps.each do |dep| | ||
| if @options[:show_summary] | ||
| spec = @resolve[dep.name].first.__materialize__ | ||
| contents << "#{" " if inside_group}# #{spec.summary}" | ||
| end | ||
|
|
||
| gem = [] | ||
| gem << " " if inside_group | ||
| gem << gem_contents(dep) | ||
| contents << gem.join | ||
| end | ||
|
|
||
| contents | ||
| end | ||
| end | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| bundle-canonical(1) -- Prettifies the Gemfile | ||
| =========================================================================== | ||
|
|
||
| ## SYNOPSIS | ||
|
|
||
| `bundle canonical` [--view] | ||
|
|
||
| ## DESCRIPTION | ||
|
|
||
| Prettifies the Gemfile by giving it consistent ordering and formatting. | ||
|
|
||
| If not, the first missing gem is listed and Bundler exits status 1. | ||
|
|
||
| ## OPTIONS | ||
|
|
||
| * `--view`: | ||
| Displays what the Gemfile would look like on change but does not change the Gemfile. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe Bundler::Gemfile do | ||
| before :each do | ||
| install_gemfile <<-G | ||
| source "file://#{gem_repo1}" | ||
| gem "weakling", "~> 0.0.1" | ||
| gem "rack-test", :group => :test | ||
| gem "rack", :groups => [:prod, :dev] | ||
| gem "rspec", :group => :test | ||
| G | ||
| end | ||
|
|
||
| context "#gem_contents" do | ||
| it "with show_groups true" do | ||
| definition = Bundler.definition | ||
| contents = subject.gem_contents(definition.dependencies.find {|d| d.name == "rack" }, true) | ||
| contents2 = subject.gem_contents(definition.dependencies.find {|d| d.name == "rack-test" }, true) | ||
| expect(contents.join).to eq("gem \"rack\", :groups => [:prod, :dev]") | ||
| expect(contents2.join).to eq("gem \"rack-test\", :group => :test") | ||
| end | ||
|
|
||
| it "with show_groups false" do | ||
| definition = Bundler.definition | ||
| contents = subject.gem_contents(definition.dependencies.find {|d| d.name == "rack" }, false) | ||
| expect(contents.join).to eq("gem \"rack\"") | ||
| end | ||
| end | ||
|
|
||
| context "#groups_wise" do | ||
| it "returns group wise gems" do | ||
| definition = Bundler.definition | ||
| a = definition.dependencies.group_by(&:groups).each_key(&:sort!).sort_by(&:first) | ||
| expected = <<-E | ||
| group :test do | ||
| gem "rack-test" | ||
| gem "rspec" | ||
| end | ||
| E | ||
|
|
||
| deps = a[2][1] | ||
| groups = a[2][0] | ||
| expect(subject.groups_wise(deps, groups).join("\n").gsub(/\n{3,}/, "\n\n")).to eq(strip_whitespace(expected)) | ||
| end | ||
| end | ||
|
|
||
| describe "#full_gemfile" do | ||
| context "without show_summary" do | ||
| subject { Bundler::Gemfile.new(:as_string => true) } | ||
|
|
||
| it "does not show summary" do | ||
| expected = <<-E | ||
| source "file://#{gem_repo1}" | ||
|
|
||
| gem "weakling", "~> 0.0.1" | ||
|
|
||
| group :dev, :prod do | ||
| gem "rack" | ||
| end | ||
|
|
||
| group :test do | ||
| gem "rack-test" | ||
| gem "rspec" | ||
| end | ||
| E | ||
| expect(subject.full_gemfile).to eq(strip_whitespace(expected)) | ||
| end | ||
| end | ||
|
|
||
| context "with show_summary" do | ||
| subject { Bundler::Gemfile.new(:as_string => true, :show_summary => true) } | ||
| it "shows summary" do | ||
| expected = <<-E | ||
| source "file://#{gem_repo1}" | ||
|
|
||
| # This is just a fake gem for testing | ||
| gem "weakling", "~> 0.0.1" | ||
|
|
||
| group :dev, :prod do | ||
| # This is just a fake gem for testing | ||
| gem "rack" | ||
| end | ||
|
|
||
| group :test do | ||
| # This is just a fake gem for testing | ||
| gem "rack-test" | ||
| # This is just a fake gem for testing | ||
| gem "rspec" | ||
| end | ||
| E | ||
| expect(subject.full_gemfile).to eq(strip_whitespace(expected)) | ||
| end | ||
| end | ||
|
|
||
| context "with inline_groups" do | ||
| subject { Bundler::Gemfile.new(:as_string => true, :inline_groups => true) } | ||
| it "shows summary" do | ||
| expected = <<-E | ||
| source "file://#{gem_repo1}" | ||
|
|
||
| gem "weakling", "~> 0.0.1" | ||
|
|
||
| gem "rack", :groups => [:dev, :prod] | ||
|
|
||
| gem "rack-test", :group => :test | ||
| gem "rspec", :group => :test | ||
| E | ||
| expect(subject.full_gemfile).to eq(strip_whitespace(expected)) | ||
| end | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe "bundle canonical" do | ||
| before :each do | ||
| install_gemfile <<-G | ||
| source "file://#{gem_repo1}" | ||
| gem "weakling", "~> 0.0.1" | ||
| gem "rack-test", :group => :test | ||
| gem "rack", :groups => [:prod, :test] | ||
| G | ||
| end | ||
|
|
||
| context "with --view option" do | ||
| it "does not update gemfile but displays expected gemfile" do | ||
| bundle! "canonical --view" | ||
| output = <<-G | ||
| source "file://#{gem_repo1}" | ||
|
|
||
| # This is just a fake gem for testing | ||
| gem "weakling", "~> 0.0.1" | ||
|
|
||
| group :prod, :test do | ||
| # This is just a fake gem for testing | ||
| gem "rack" | ||
| end | ||
|
|
||
| group :test do | ||
| # This is just a fake gem for testing | ||
| gem "rack-test" | ||
| end | ||
| G | ||
|
|
||
| expect(out).to eq(strip_whitespace(output)) | ||
| gemfile_should_be <<-G | ||
| source "file://#{gem_repo1}" | ||
| gem "weakling", "~> 0.0.1" | ||
| gem "rack-test", :group => :test | ||
| gem "rack", :groups => [:prod, :test] | ||
| G | ||
| end | ||
| end | ||
|
|
||
| context "without --view option" do | ||
| it "updates gemfile" do | ||
| bundle! "canonical" | ||
|
|
||
| gemfile_should_be <<-G | ||
| source "file://#{gem_repo1}" | ||
|
|
||
| # This is just a fake gem for testing | ||
| gem "weakling", "~> 0.0.1" | ||
|
|
||
| group :prod, :test do | ||
| # This is just a fake gem for testing | ||
| gem "rack" | ||
| end | ||
|
|
||
| group :test do | ||
| # This is just a fake gem for testing | ||
| gem "rack-test" | ||
| end | ||
| G | ||
| end | ||
| end | ||
| end |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we''l need to come up with a better name for this, but we can do so in the RFC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was thinking maybe
prettifyor something on those lines.