annotate_gem 0.0.8

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: 7e0ee9922534ca6c7e763fd617f8e81a461ff4e1
4
+ data.tar.gz: d60f74fff3ca5131bd5beacbc7729435a973ab01
5
+ SHA512:
6
+ metadata.gz: 3323eb1ba24e40ca46fb3f75c4ccb72ead72c4c9279fcebe841ee24b7de4eb51af7aa0fd3dd162d2367da6f6e3ea74aabb5c2748bf41cecff5e8d3a92b2c166c
7
+ data.tar.gz: cbb7b96c3789ff8123299bc315742c727521b1f9eee40abf53c9f3078a4b1033b3ca19e9ae16e9820093cb8fc901c3694448bea26207293df302dc830c9a40ad
data/.gitignore ADDED
@@ -0,0 +1,15 @@
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
15
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grub.gemspec
4
+ gemspec
5
+
6
+ # An IRB alternative and runtime developer console (http://pryrepl.org)
7
+ gem "pry"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Ivan Tse
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,60 @@
1
+ # AnnotateGem
2
+
3
+ `annotate_gem` is command line tool that will add useful comments to your Gemfile. For each gem, `annotate_gem` will create a comment with the gem's description and the gem's website. For example, a Gemfile containing the following
4
+
5
+ ```ruby
6
+ gem "rails"
7
+ gem "nokogiri"
8
+ gem "brakeman"
9
+ ```
10
+
11
+ will be converted into something that is more descriptive and is self-documenting:
12
+
13
+ ```ruby
14
+ # Full-stack web application framework. (http://www.rubyonrails.org)
15
+ gem "rails"
16
+ # Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser (http://nokogiri.org)
17
+ gem "nokogiri"
18
+ # Security vulnerability scanner for Ruby on Rails. (http://brakemanscanner.org)
19
+ gem "brakeman"
20
+ ```
21
+
22
+ The motivation for `annotate_gem` is that developers often open a Gemfile and not know what many of the listed gems are actually for. It's hard to track down which gem is providing which functionality. This is a common problem since many gem names do not reflect the actual feature.
23
+
24
+ If you do _not_ want to install the gem, you can also visit <https://annotate_gem.herokuapp.com/> which is a web interface for `annotate_gem`.
25
+
26
+ ## Installation
27
+
28
+ ```
29
+ $ gem install annotate_gem
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ Running `annotate_gem` itself will add comments to the current directory's `Gemfile`.
35
+
36
+ ```
37
+ $ cat Gemfile
38
+ source 'https://rubygems.org'
39
+ gem "pry"
40
+ $ annotate_gem
41
+ $ cat Gemfile
42
+ source 'https://rubygems.org'
43
+ # An IRB alternative and runtime developer console (http://pryrepl.org)
44
+ gem "pry"
45
+ ```
46
+
47
+ `annotate_gem` has several options and you can see them via `annotate_gem -h`. `annotate_gem` also works with specifying a single gem name:
48
+
49
+ ```
50
+ $ annotate_gem aasm
51
+ State machine mixin for Ruby objects (https://github.com/aasm/aasm)
52
+ ```
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it ( https://github.com/ivantsepp/annotate_gem/fork )
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 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.libs << "test"
6
+ t.test_files = FileList['test/**/*test.rb']
7
+ t.verbose = true
8
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'annotate_gem/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "annotate_gem"
8
+ spec.version = AnnotateGem::VERSION
9
+ spec.authors = ["Ivan Tse"]
10
+ spec.email = ["ivan.tse1@gmail.com"]
11
+ spec.summary = AnnotateGem::DESCRIPTION
12
+ spec.description = <<-DESCRIPTION.gsub(/^\s+/, "").gsub(/\n/, " ")
13
+ Clarify your dependencies by adding a detailed comment to each line in Gemfile specifying the
14
+ gem's summary and its website if any.
15
+ DESCRIPTION
16
+ spec.homepage = "https://github.com/ivantsepp/annotate_gem"
17
+ spec.license = "MIT"
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_runtime_dependency "bundler", "~> 1.11.2"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "minitest", "~> 5.0"
27
+ spec.add_development_dependency "mocha", "~> 1.1"
28
+ end
data/bin/annotate_gem ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), "../lib"))
4
+
5
+ require "annotate_gem/cli"
6
+ require "annotate_gem"
7
+
8
+ AnnotateGem::CLI.new.run(ARGV)
@@ -0,0 +1,8 @@
1
+ require "annotate_gem/version"
2
+ require "bundler"
3
+ require "annotate_gem/gem_line"
4
+ require "annotate_gem/gemfile"
5
+ require "annotate_gem/spec_finder"
6
+
7
+ module AnnotateGem
8
+ end
@@ -0,0 +1,41 @@
1
+ require "annotate_gem/options"
2
+
3
+ module AnnotateGem
4
+ class CLI
5
+ def run(args)
6
+ options = Options.new.parse!(args)
7
+ if args.empty?
8
+ run_for_gemfile(options)
9
+ else
10
+ run_for_gem(args.pop, options)
11
+ end
12
+ end
13
+
14
+ def run_for_gemfile(options = {})
15
+ Bundler.configure
16
+ gemfile = Gemfile.new(Bundler.default_gemfile, options)
17
+ gemfile.parse
18
+ unless gemfile.gem_lines.empty?
19
+ SpecFinder.find_specs_for(gemfile.gem_lines, &self.method(:print_progress))
20
+ gemfile.write_comments
21
+ end
22
+ end
23
+
24
+ def run_for_gem(gem_name, options = {})
25
+ gem_line = GemLine.new(name: gem_name, options: options)
26
+ SpecFinder.find_specs_for(gem_line, &self.method(:print_progress))
27
+
28
+ info = gem_line.info
29
+ info = "No information to show" if info.strip.empty?
30
+ puts info
31
+ end
32
+
33
+ private
34
+
35
+ def print_progress(processing, total)
36
+ print "Fetching gem metadata..." if processing.zero?
37
+ print "."
38
+ print "\n" if processing == total
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,65 @@
1
+ module AnnotateGem
2
+ class GemLine
3
+
4
+ attr_accessor :name, :original_line, :location, :prev_line_comment, :spec, :options
5
+
6
+ def initialize(*args)
7
+ named_params = args.last.respond_to?(:[]) && args.last
8
+ @name = (named_params && named_params[:name]) || args[0]
9
+ @original_line = (named_params && named_params[:original_line]) || args[1]
10
+ @location = (named_params && named_params[:location]) || args[2]
11
+ @prev_line_comment = (named_params && named_params[:prev_line_comment]) || args[3]
12
+ @options = (named_params && named_params[:options]) || named_params
13
+ end
14
+
15
+ def comment
16
+ leading_spaces = original_line[0..leading_spaces_count - 1] if leading_spaces_count > 0
17
+ comment = "#{leading_spaces}# #{info}"
18
+ end
19
+
20
+ def info
21
+ output = if options[:website_only]
22
+ website
23
+ elsif options[:description_only]
24
+ description
25
+ else
26
+ description_and_website
27
+ end
28
+ output << "\n"
29
+ end
30
+
31
+ def should_insert?
32
+ !info.strip.empty? && !already_added_comment && !existing_comment_option
33
+ end
34
+
35
+ private
36
+
37
+ def already_added_comment
38
+ prev_line_comment && prev_line_comment.include?(comment)
39
+ end
40
+
41
+ # if there exists a prev_line_comment and the user has specified new_comments_only
42
+ def existing_comment_option
43
+ prev_line_comment && options[:new_comments_only]
44
+ end
45
+
46
+ def leading_spaces_count
47
+ original_line.length - original_line.lstrip.length
48
+ end
49
+
50
+ def description
51
+ "#{spec.summary}" if spec
52
+ end
53
+
54
+ def website
55
+ "#{spec.homepage.to_s}" if spec
56
+ end
57
+
58
+ def description_and_website
59
+ output = "#{description}"
60
+ output << " (#{website})" unless website.nil? || website.empty?
61
+ output
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,46 @@
1
+ module AnnotateGem
2
+ class Gemfile
3
+
4
+ GEM_LINE_REGEX = /\A\s*gem[\s(]+["'](?<name>[^'"]*)["']/.freeze
5
+
6
+ attr_accessor :gemfile_path, :gem_lines, :source, :options
7
+
8
+ def initialize(gemfile_path, options = {})
9
+ @gemfile_path = gemfile_path
10
+ @source = []
11
+ @gem_lines = []
12
+ @options = options
13
+ end
14
+
15
+ def parse
16
+ self.source = File.readlines(gemfile_path)
17
+ source.each_with_index do |line, i|
18
+ if match = GEM_LINE_REGEX.match(line)
19
+ prev_line = source[i - 1] if i > 0
20
+ prev_line_comment = prev_line if is_line_a_comment?(prev_line)
21
+ self.gem_lines << GemLine.new(
22
+ name: match[:name],
23
+ original_line: line,
24
+ location: i,
25
+ prev_line_comment: prev_line_comment,
26
+ options: options
27
+ )
28
+ end
29
+ end
30
+ end
31
+
32
+ def write_comments
33
+ gem_lines.reverse.each do |gem_line|
34
+ source.insert(gem_line.location, gem_line.comment) if gem_line.should_insert?
35
+ end
36
+ File.write(gemfile_path, source.join)
37
+ end
38
+
39
+ private
40
+
41
+ def is_line_a_comment?(line)
42
+ line && line.strip.start_with?("#")
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,66 @@
1
+ require "optparse"
2
+
3
+ module AnnotateGem
4
+ class Options
5
+
6
+ attr_accessor :options, :options_parser
7
+
8
+ def initialize
9
+ @options = {}
10
+ @options_parser = OptionParser.new do |opts|
11
+ add_banner(opts)
12
+ add_tail_options(opts)
13
+ add_info_options(opts)
14
+ add_gemfile_comment_options(opts)
15
+ end
16
+ end
17
+
18
+ def parse!(args)
19
+ options_parser.parse!(args)
20
+ validate_options
21
+ options
22
+ end
23
+
24
+ private
25
+
26
+ def validate_options
27
+ info_flags = options[:website_only] && options[:description_only]
28
+ raise ArgumentError, "Cannot set both --website-only and --description-only flags" if info_flags
29
+ end
30
+
31
+ def add_info_options(opts)
32
+ opts.on("--website-only", "Only output the website") do
33
+ options[:website_only] = true
34
+ end
35
+ opts.on("--description-only", "Only output the description") do
36
+ options[:description_only] = true
37
+ end
38
+ end
39
+
40
+ def add_gemfile_comment_options(opts)
41
+ opts.on("--new-comments-only", "Only add a comment to gemfile if there isn't a comment already") do
42
+ options[:new_comments_only] = true
43
+ end
44
+ end
45
+
46
+ def add_banner(opts)
47
+ opts.banner = <<-BANNER.gsub(/\A\s{8}/, '')
48
+ #{AnnotateGem::DESCRIPTION}
49
+ Usage: #{opts.program_name} [options]
50
+ #{opts.program_name} [gem name]
51
+ BANNER
52
+ end
53
+
54
+ def add_tail_options(opts)
55
+ opts.on_tail("-h", "--help", "Show this message") do
56
+ puts opts
57
+ exit
58
+ end
59
+ opts.on_tail("-v", "--version", "Show version") do
60
+ puts AnnotateGem::VERSION
61
+ exit
62
+ end
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,43 @@
1
+ module AnnotateGem
2
+ module SpecFinder
3
+ extend self
4
+
5
+ def find_specs_for(gem_lines, &block)
6
+ gem_lines = Array(gem_lines)
7
+ find_matching_specs_for(gem_lines)
8
+ gems_to_fetch = gem_lines.select { |gem_line| gem_line.spec.nil? }
9
+ fetch_specs_for(gems_to_fetch, &block) if gems_to_fetch.any?
10
+ end
11
+
12
+ def find_matching_specs_for(gem_lines)
13
+ gem_lines.each do |line|
14
+ matching_specs = Gem::Dependency.new(line.name).matching_specs
15
+ # TODO: need to find latest
16
+ line.spec = matching_specs.first if matching_specs.any?
17
+ end
18
+ end
19
+
20
+ def fetch_specs_for(gem_lines)
21
+ total = gem_lines.length
22
+ processing = 0
23
+ yield processing, total if block_given?
24
+ # TODO: Support private sources
25
+ remote = Bundler::Source::Rubygems::Remote.new(Gem.sources.first.uri)
26
+ fetcher = Bundler::Fetcher.new(remote)
27
+ dependency_fetcher = fetcher.fetchers.find {|f| Bundler::Fetcher::Dependency === f }
28
+ versions, _ = dependency_fetcher.dependency_specs(gem_lines.collect(&:name))
29
+ gem_lines.each do |gem_line|
30
+ processing += 1
31
+ yield processing, total if block_given?
32
+ gem_versions = versions.select { |v| v.first == gem_line.name }
33
+ next if gem_versions.empty? # couldn't find version on RubyGems so go to next one
34
+ version = find_latest_version(gem_versions)
35
+ gem_line.spec = fetcher.fetch_spec([gem_line.name, version])
36
+ end
37
+ end
38
+
39
+ def find_latest_version(versions)
40
+ versions.sort_by { |v| v[1] }.last[1]
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,4 @@
1
+ module AnnotateGem
2
+ VERSION = "0.0.8".freeze
3
+ DESCRIPTION = "Add comments to your Gemfile with each dependency's description.".freeze
4
+ end
@@ -0,0 +1,23 @@
1
+ require "test_helper"
2
+ require "annotate_gem/cli"
3
+
4
+ # Acts as integration test since it will actually fetch data from API
5
+ class AnnotateGem::CLITest < Minitest::Test
6
+
7
+ def test_run_for_gemfile
8
+ with_gemfile(File.read(gemfile_path)) do |path|
9
+ Bundler.expects(:default_gemfile).returns(path)
10
+ out, _ = capture_io do
11
+ AnnotateGem::CLI.new.run_for_gemfile
12
+ end
13
+ assert_equal File.read(annotated_gemfile_path), File.read(path)
14
+ end
15
+ end
16
+
17
+ def test_run_for_gem
18
+ out, _ = capture_io do
19
+ AnnotateGem::CLI.new.run_for_gem("annotate_gem")
20
+ end
21
+ assert_equal "Add comments to your Gemfile with each dependency's description. (https://github.com/ivantsepp/annotate_gem)\n", out
22
+ end
23
+ end
@@ -0,0 +1,79 @@
1
+ require "test_helper"
2
+
3
+ class AnnotateGem::GemLineTest < Minitest::Test
4
+
5
+ def test_info
6
+ gem_line = create_gem_line
7
+ spec = stub(summary: "Hello world", homepage: "http://example.com")
8
+ gem_line.spec = spec
9
+ assert_equal "Hello world (http://example.com)\n", gem_line.info
10
+ end
11
+
12
+ def test_info_with_website_only
13
+ gem_line = create_gem_line(options: { website_only: true })
14
+ spec = stub(summary: "Hello world", homepage: "http://example.com")
15
+ gem_line.spec = spec
16
+ assert_equal "http://example.com\n", gem_line.info
17
+ end
18
+
19
+ def test_info_with_description_only
20
+ gem_line = create_gem_line(options: { description_only: true })
21
+ spec = stub(summary: "Hello world", homepage: "http://example.com")
22
+ gem_line.spec = spec
23
+ assert_equal "Hello world\n", gem_line.info
24
+ end
25
+
26
+ def test_should_insert_with_no_info
27
+ gem_line = create_gem_line
28
+ gem_line.expects(:info).returns("")
29
+ refute gem_line.should_insert?
30
+ end
31
+
32
+ def test_should_insert_with_no_spec
33
+ gem_line = create_gem_line
34
+ refute gem_line.should_insert?
35
+ end
36
+
37
+ def test_should_insert_with_already_added_comment
38
+ gem_line = create_gem_line(prev_line_comment: "# Hello world (http://example.com)\n")
39
+ spec = stub(summary: "Hello world", homepage: "http://example.com")
40
+ gem_line.spec = spec
41
+ refute gem_line.should_insert?
42
+ end
43
+
44
+ def test_should_insert_with_new_comments_only
45
+ gem_line = create_gem_line(
46
+ prev_line_comment: "# This is an existing comment\n",
47
+ options: { new_comments_only: true }
48
+ )
49
+ spec = stub(summary: "Hello world", homepage: "http://example.com")
50
+ gem_line.spec = spec
51
+ refute gem_line.should_insert?
52
+ end
53
+
54
+ def test_comment
55
+ gem_line = create_gem_line
56
+ spec = stub(summary: "Hello world", homepage: "http://example.com")
57
+ gem_line.spec = spec
58
+ assert_equal "# Hello world (http://example.com)\n", gem_line.comment
59
+ end
60
+
61
+ def test_comment_with_indentation_in_original_line
62
+ gem_line = AnnotateGem::GemLine.new(
63
+ name: "annotate_gem",
64
+ original_line: " \tgem 'annotate_gem'"
65
+ )
66
+ spec = stub(summary: "Hello world", homepage: "http://example.com")
67
+ gem_line.spec = spec
68
+ assert_equal " \t# Hello world (http://example.com)\n", gem_line.comment
69
+ end
70
+
71
+ private
72
+
73
+ def create_gem_line(options = {})
74
+ AnnotateGem::GemLine.new(
75
+ { name: "annotate_gem", original_line: "gem 'annotate_gem'" }.merge(options)
76
+ )
77
+ end
78
+
79
+ end
@@ -0,0 +1,71 @@
1
+ require "test_helper"
2
+
3
+ class AnnotateGem::GemfileTest < Minitest::Test
4
+
5
+ def test_parses_source
6
+ gemfile = gemfile_for(unindent(<<-GEMFILE))
7
+ hello
8
+ world!
9
+ GEMFILE
10
+ assert 2, gemfile.source.length
11
+ assert_equal "hello\n", gemfile.source.first
12
+ assert_equal "world!\n", gemfile.source.last
13
+ end
14
+
15
+ def test_parses_gem_lines
16
+ AnnotateGem::GemLine.expects(:new).with(
17
+ name: "rails",
18
+ original_line: "gem \"rails\"\n",
19
+ location: 0,
20
+ prev_line_comment: nil,
21
+ options: {}
22
+ ).once
23
+ AnnotateGem::GemLine.expects(:new).with(
24
+ name: "annotate_gem",
25
+ original_line: "gem \"annotate_gem\"\n",
26
+ location: 2,
27
+ prev_line_comment: "# this gem has a comment\n",
28
+ options: {}
29
+ ).once
30
+ gemfile = gemfile_for(unindent(<<-GEMFILE))
31
+ gem "rails"
32
+ # this gem has a comment
33
+ gem "annotate_gem"
34
+ # gem "commented_out"
35
+ GEMFILE
36
+ assert_equal 2, gemfile.gem_lines.length
37
+ end
38
+
39
+ def test_write_comments
40
+ with_gemfile("gem 'rails'") do |path|
41
+ gemfile = AnnotateGem::Gemfile.new(path)
42
+ gemfile.gem_lines = [mock(location: 0, comment: "Rails description!\n", should_insert?: true)]
43
+ gemfile.source = ["gem 'rails'"]
44
+ gemfile.write_comments
45
+ assert_equal "Rails description!\ngem 'rails'", File.read(path)
46
+ end
47
+ end
48
+
49
+ def test_that_options_are_passed_through
50
+ AnnotateGem::GemLine.expects(:new).with(
51
+ name: "rails",
52
+ original_line: "gem 'rails'",
53
+ location: 0,
54
+ prev_line_comment: nil,
55
+ options: { description_only: true }
56
+ ).once
57
+ gemfile = gemfile_for("gem 'rails'", description_only: true)
58
+ end
59
+
60
+ private
61
+
62
+ def gemfile_for(content, options = {})
63
+ gemfile = nil
64
+ with_gemfile(content) do |path|
65
+ gemfile = AnnotateGem::Gemfile.new(path, options)
66
+ gemfile.parse
67
+ end
68
+ gemfile
69
+ end
70
+
71
+ end
@@ -0,0 +1,79 @@
1
+ require "test_helper"
2
+
3
+ class AnnotateGem::SpecFinderTest < Minitest::Test
4
+ def test_find_specs_for
5
+ gem_line_1 = mock(spec: nil)
6
+ gem_line_2 = mock(spec: "spec")
7
+ AnnotateGem::SpecFinder.expects(:find_matching_specs_for).with([gem_line_1, gem_line_2])
8
+ AnnotateGem::SpecFinder.expects(:fetch_specs_for).with([gem_line_1])
9
+ AnnotateGem::SpecFinder.find_specs_for([gem_line_1, gem_line_2])
10
+ end
11
+
12
+ def test_find_matching_specs_for
13
+ spec_1 = mock
14
+ gem_line_1 = mock(name: "1")
15
+ gem_line_1.expects(:spec=).with(spec_1)
16
+ spec_2 = mock
17
+ gem_line_2 = mock(name: "2")
18
+ gem_line_2.expects(:spec=).with(spec_2)
19
+ gem_lines = [gem_line_1, gem_line_2]
20
+ Gem::Dependency.expects(:new).with("1").returns(mock(matching_specs: [spec_1]))
21
+ Gem::Dependency.expects(:new).with("2").returns(mock(matching_specs: [spec_2]))
22
+ AnnotateGem::SpecFinder.find_matching_specs_for(gem_lines)
23
+ end
24
+
25
+ def test_fetch_specs_for
26
+ original_stdout = $stdout
27
+ $stdout = StringIO.new
28
+
29
+ spec_1 = mock
30
+ gem_line_1 = mock
31
+ gem_line_1.stubs(name: "1")
32
+ gem_line_1.expects(:spec=).with(spec_1)
33
+ spec_2 = mock
34
+ gem_line_2 = mock
35
+ gem_line_2.stubs(name: "2")
36
+ gem_line_2.expects(:spec=).with(spec_2)
37
+
38
+ dependency_fetcher_mock = Bundler::Fetcher::Dependency.new(nil, nil, nil)
39
+ Bundler::Fetcher.any_instance.expects(:fetchers).returns([dependency_fetcher_mock])
40
+ dependency_fetcher_mock.expects(:dependency_specs).with(["1", "2"]).returns([[
41
+ ["1", Gem::Version.new("1")],
42
+ ["2", Gem::Version.new("1")],
43
+ ], "dependencies here"])
44
+ AnnotateGem::SpecFinder.expects(:find_latest_version).returns(Gem::Version.new("1")).twice
45
+ Bundler::Fetcher.any_instance.expects(:fetch_spec).with(["1", Gem::Version.new("1")]).returns(spec_1)
46
+ Bundler::Fetcher.any_instance.expects(:fetch_spec).with(["2", Gem::Version.new("1")]).returns(spec_2)
47
+ yielded_values = []
48
+ AnnotateGem::SpecFinder.fetch_specs_for([gem_line_1, gem_line_2]) do |*args|
49
+ yielded_values << args
50
+ end
51
+ assert_equal [[0, 2], [1, 2], [2, 2]], yielded_values
52
+ $stdout = original_stdout
53
+ end
54
+
55
+ def test_fetch_unknown_specs
56
+ original_stdout = $stdout
57
+ $stdout = StringIO.new
58
+
59
+ gem_line_1 = mock
60
+ gem_line_1.stubs(name: "1")
61
+ gem_line_1.expects(:spec=).never
62
+
63
+ dependency_fetcher_mock = Bundler::Fetcher::Dependency.new(nil, nil, nil)
64
+ Bundler::Fetcher.any_instance.expects(:fetchers).returns([dependency_fetcher_mock])
65
+ dependency_fetcher_mock.expects(:dependency_specs).with(["1"]).returns([[], "dependencies here"])
66
+ Bundler::Fetcher.any_instance.expects(:fetch_spec).never
67
+ AnnotateGem::SpecFinder.fetch_specs_for([gem_line_1])
68
+
69
+ $stdout = original_stdout
70
+ end
71
+
72
+ def test_find_latest_version
73
+ versions = [
74
+ ["rails", Gem::Version.new("2.3.5")],
75
+ ["rails", Gem::Version.new("4")]
76
+ ]
77
+ assert_equal Gem::Version.new("4"), AnnotateGem::SpecFinder.find_latest_version(versions)
78
+ end
79
+ end
@@ -0,0 +1,31 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'rails', '4.2.1'
4
+ gem 'sqlite3'
5
+ gem 'sass-rails', '~> 5.0'
6
+ gem 'uglifier', '>= 1.3.0'
7
+ gem 'coffee-rails', '~> 4.1.0'
8
+ # See https://github.com/rails/execjs#readme for more supported runtimes
9
+ # gem 'therubyracer', platforms: :ruby
10
+
11
+ gem 'jquery-rails'
12
+ gem 'turbolinks'
13
+ gem 'jbuilder', '~> 2.0'
14
+ # bundle exec rake doc:rails generates the API under doc/api.
15
+ gem 'sdoc', '~> 0.4.0', group: :doc
16
+
17
+ # Use ActiveModel has_secure_password
18
+ # gem 'bcrypt', '~> 3.1.7'
19
+
20
+ # Use Unicorn as the app server
21
+ # gem 'unicorn'
22
+
23
+ # Use Capistrano for deployment
24
+ # gem 'capistrano-rails', group: :development
25
+
26
+ group :development, :test do
27
+ gem 'byebug'
28
+ gem 'web-console', '~> 2.0'
29
+ # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
30
+ gem 'spring'
31
+ end
@@ -0,0 +1,43 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Full-stack web application framework. (http://rubyonrails.org)
4
+ gem 'rails', '4.2.1'
5
+ # This module allows Ruby programs to interface with the SQLite3 database engine (http://www.sqlite.org) (https://github.com/sparklemotion/sqlite3-ruby)
6
+ gem 'sqlite3'
7
+ # Sass adapter for the Rails asset pipeline. (https://github.com/rails/sass-rails)
8
+ gem 'sass-rails', '~> 5.0'
9
+ # Ruby wrapper for UglifyJS JavaScript compressor (http://github.com/lautis/uglifier)
10
+ gem 'uglifier', '>= 1.3.0'
11
+ # CoffeeScript adapter for the Rails asset pipeline. (https://github.com/rails/coffee-rails)
12
+ gem 'coffee-rails', '~> 4.1.0'
13
+ # See https://github.com/rails/execjs#readme for more supported runtimes
14
+ # gem 'therubyracer', platforms: :ruby
15
+
16
+ # Use jQuery with Rails 4+ (http://rubygems.org/gems/jquery-rails)
17
+ gem 'jquery-rails'
18
+ # Turbolinks makes navigating your web application faster (https://github.com/turbolinks/turbolinks-rails)
19
+ gem 'turbolinks'
20
+ # Create JSON structures via a Builder-style DSL (https://github.com/rails/jbuilder)
21
+ gem 'jbuilder', '~> 2.0'
22
+ # bundle exec rake doc:rails generates the API under doc/api.
23
+ # rdoc html with javascript search index. (http://github.com/voloko/sdoc)
24
+ gem 'sdoc', '~> 0.4.0', group: :doc
25
+
26
+ # Use ActiveModel has_secure_password
27
+ # gem 'bcrypt', '~> 3.1.7'
28
+
29
+ # Use Unicorn as the app server
30
+ # gem 'unicorn'
31
+
32
+ # Use Capistrano for deployment
33
+ # gem 'capistrano-rails', group: :development
34
+
35
+ group :development, :test do
36
+ # Ruby 2.0 fast debugger - base + CLI (http://github.com/deivid-rodriguez/byebug)
37
+ gem 'byebug'
38
+ # A debugging tool for your Ruby on Rails applications. (https://github.com/rails/web-console)
39
+ gem 'web-console', '~> 2.0'
40
+ # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
41
+ # Rails application preloader (https://github.com/rails/spring)
42
+ gem 'spring'
43
+ end
@@ -0,0 +1,31 @@
1
+ require "minitest/autorun"
2
+ require "mocha/mini_test"
3
+ require "annotate_gem"
4
+
5
+ module TestHelpers
6
+
7
+ def gemfile_path
8
+ File.join(File.dirname(__FILE__), "fixtures", "Gemfile")
9
+ end
10
+
11
+ def annotated_gemfile_path
12
+ File.join(File.dirname(__FILE__), "fixtures", "Gemfile_annotated")
13
+ end
14
+
15
+ def with_gemfile(content)
16
+ file = Tempfile.new('gemfile')
17
+ file.write(content)
18
+ file.close
19
+ yield(file.path)
20
+ file.unlink
21
+ end
22
+
23
+ def unindent(str)
24
+ str.gsub(/^#{str.scan(/^[ ]+(?=\S)/).min}/, "")
25
+ end
26
+
27
+ end
28
+
29
+ class Minitest::Test
30
+ include TestHelpers
31
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: annotate_gem
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.8
5
+ platform: ruby
6
+ authors:
7
+ - Ivan Tse
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.11.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.11.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ description: 'Clarify your dependencies by adding a detailed comment to each line
70
+ in Gemfile specifying the gem''s summary and its website if any. '
71
+ email:
72
+ - ivan.tse1@gmail.com
73
+ executables:
74
+ - annotate_gem
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - annotate_gem.gemspec
84
+ - bin/annotate_gem
85
+ - lib/annotate_gem.rb
86
+ - lib/annotate_gem/cli.rb
87
+ - lib/annotate_gem/gem_line.rb
88
+ - lib/annotate_gem/gemfile.rb
89
+ - lib/annotate_gem/options.rb
90
+ - lib/annotate_gem/spec_finder.rb
91
+ - lib/annotate_gem/version.rb
92
+ - test/annotate_gem/cli_test.rb
93
+ - test/annotate_gem/gem_line_test.rb
94
+ - test/annotate_gem/gemfile_test.rb
95
+ - test/annotate_gem/spec_finder_test.rb
96
+ - test/fixtures/Gemfile
97
+ - test/fixtures/Gemfile_annotated
98
+ - test/test_helper.rb
99
+ homepage: https://github.com/ivantsepp/annotate_gem
100
+ licenses:
101
+ - MIT
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.6.3
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Add comments to your Gemfile with each dependency's description.
123
+ test_files:
124
+ - test/annotate_gem/cli_test.rb
125
+ - test/annotate_gem/gem_line_test.rb
126
+ - test/annotate_gem/gemfile_test.rb
127
+ - test/annotate_gem/spec_finder_test.rb
128
+ - test/fixtures/Gemfile
129
+ - test/fixtures/Gemfile_annotated
130
+ - test/test_helper.rb