lapidarius 1.0.0

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: 0c2f5e0adba9a26b9c587019623572558703d340
4
+ data.tar.gz: 57c04cf09af054ce51b002eace5c90ee4a77000b
5
+ SHA512:
6
+ metadata.gz: 4321b2c5a80c88fd794683dc3a9a4905beda4e9fcc655c0cd6fa1445fb023456bdb22d38d8f4e68a5c8e9fcf406ceefa248c0923355eefff708dc69f50577852
7
+ data.tar.gz: 45033c48b91c70b94e6c60af650084e0a38945aae9942e7d8ef8ab0962924f9c08b8bf9ebc5f55aa6cf0f39e82c9e77824595d500c04bb66500c281ba7017253
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.1.8
5
+ - 2.2.1
6
+ - 2.3.1
7
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gem_dependencies.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ ## Table of Contents
2
+
3
+ * [Scope](#scope)
4
+ * [Alternatives](#alternatives)
5
+ * [gem dep](#gem-dep)
6
+ * [bundle viz](#bundle-viz)
7
+ * [Usage](#usage)
8
+ * [Unique dependencies](#unique-dependencies)
9
+ * [Recursive print](#recursive-print)
10
+ * [Warning](#warning)
11
+
12
+ ## Scope
13
+ This gem is aimed to list recursively the **runtime dependencies** footprint of the specified gem.
14
+
15
+ ### Alternatives
16
+ Some alternatives exists:
17
+
18
+ #### gem dep
19
+ The standard *gem dep* command just unearth one level of dependencies.
20
+
21
+ #### bundle viz
22
+ The *bundle viz* command relies on the Gemfile and the [graphviz](http://www.graphviz.org/) library to generate a visual representation of the gem inter-dependencies.
23
+ While it is great to visualize inter-dependencies, i have hard times figuring out gem's runtime footprint.
24
+
25
+ ## Usage
26
+ The library relies on the *Gem::Commands::DependencyCommand* class (the one invoked by the *gem dep* command line), invoking it recursively to deeply fetch dependencies.
27
+
28
+ ### Unique dependencies
29
+ The command outcome includes all of the unique (by name) nested runtime dependencies:
30
+ ```
31
+ $ ./bin/lapidarius --gem=grape
32
+
33
+ grape (0.17.0) 20
34
+ ------------------------------
35
+ activesupport (>= 0)
36
+ builder (>= 0)
37
+ hashie (>= 2.1.0)
38
+ multi_json (>= 1.3.2)
39
+ multi_xml (>= 0.5.2)
40
+ mustermann19 (~> 0.4.3)
41
+ rack (>= 1.3.0)
42
+ rack-accept (>= 0)
43
+ virtus (>= 1.0.0)
44
+ concurrent-ruby (>= 1.0.2, ~> 1.0)
45
+ i18n (~> 0.7)
46
+ minitest (~> 5.1)
47
+ tzinfo (~> 1.1)
48
+ thread_safe (~> 0.1)
49
+ enumerable-lazy (>= 0)
50
+ axiom-types (~> 0.1)
51
+ coercible (~> 1.0)
52
+ descendants_tracker (>= 0.0.3, ~> 0.0)
53
+ equalizer (>= 0.0.9, ~> 0.0)
54
+ ice_nine (~> 0.11.0)
55
+
56
+ ```
57
+
58
+ ### Recursive print
59
+ To print dependencies hierarchy recursively, provide the *--recursive* flag. Duplicates are not counted:
60
+ ```
61
+ $ ./bin/lapidarius --gem=sinatra --recursive
62
+
63
+ sinatra (1.4.7) 3
64
+ ------------------------------
65
+ rack (~> 1.5)
66
+ rack-protection (~> 1.4)
67
+ rack (>= 0)
68
+ tilt (< 3, >= 1.3)
69
+
70
+ ```
71
+
72
+ ### Warning
73
+ Consider only the gems installed on your system are scanned for their own dependencies, no remote fetching is performed.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:spec) do |t|
5
+ t.libs << "spec"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["spec/**/*_spec.rb"]
8
+ end
9
+
10
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "lapidarius"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/lapidarius ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ lib = File.expand_path("../../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require "lapidarius"
6
+
7
+ Lapidarius::CLI.new(ARGV.clone).call
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "lapidarius/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "lapidarius"
8
+ s.version = Lapidarius::VERSION
9
+ s.authors = ["costajob"]
10
+ s.email = ["costajob@gmail.com"]
11
+ s.homepage = "https://github.com/costajob/lapidarius"
12
+ s.summary = "A tiny library to visualize and count gem dependencies recursively"
13
+ s.license = "MIT"
14
+ s.required_ruby_version = ">= 2.1.8"
15
+
16
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ s.bindir = "exe"
18
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "bundler", "~> 1.12"
22
+ s.add_development_dependency "rake", "~> 10.0"
23
+ s.add_development_dependency "minitest", "~> 5.0"
24
+ end
data/lib/lapidarius.rb ADDED
@@ -0,0 +1,5 @@
1
+ lib = File.expand_path("../../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require "lapidarius/version"
5
+ require "lapidarius/cli"
@@ -0,0 +1,51 @@
1
+ require "optparse"
2
+ require "lapidarius/cutter"
3
+ require "lapidarius/renderer"
4
+
5
+ module Lapidarius
6
+ class CLI
7
+ class NoGemError < ArgumentError; end
8
+
9
+ def initialize(args, io = STDOUT)
10
+ @args = args
11
+ @io = io
12
+ @gem = nil
13
+ @recursive = nil
14
+ end
15
+
16
+ def call(cmd_klass = Command)
17
+ parser.parse!(@args)
18
+ fail NoGemError, "please specify the name of an installed gem!" unless @gem
19
+ gem = cutter(cmd_klass).call
20
+ renderer(gem).call(@io)
21
+ end
22
+
23
+ private def parser
24
+ OptionParser.new do |opts|
25
+ opts.banner = "Usage: ./bin/lapidarius --gem=sinatra --recursive"
26
+
27
+ opts.on("-gGEM", "--gem=GEM", "The gem name to scan") do |gem|
28
+ @gem = gem
29
+ end
30
+
31
+ opts.on("-r", "--recursive", "Print dependencies recursively") do |recursive|
32
+ @recursive = recursive
33
+ end
34
+
35
+ opts.on("-h", "--help", "Prints this help") do
36
+ @io.puts opts
37
+ exit
38
+ end
39
+ end
40
+ end
41
+
42
+ private def cutter(cmd_klass)
43
+ @cutter = Lapidarius::Cutter.new(gem: @gem, cmd_klass: cmd_klass)
44
+ end
45
+
46
+ private def renderer(gem)
47
+ Lapidarius::Renderer::new(gem: gem, recursive: @recursive)
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,18 @@
1
+ require "rubygems/commands/dependency_command"
2
+ require "lapidarius/ui"
3
+
4
+ module Lapidarius
5
+ class Command
6
+ def initialize(dep_klass: ::Gem::Commands::DependencyCommand, ui_klass: UI)
7
+ @dep = dep_klass.new
8
+ @dep.ui = ui_klass.new
9
+ end
10
+
11
+ def call(gem)
12
+ @dep.ui.clear!
13
+ @dep.invoke(gem)
14
+ @dep.ui.out
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,38 @@
1
+ require "lapidarius/gem"
2
+ require "lapidarius/command"
3
+
4
+ module Lapidarius
5
+ class Cutter
6
+ DEVELOPMENT = "development"
7
+
8
+ def initialize(gem:, cmd_klass: Command)
9
+ @gem = gem
10
+ @cmd = cmd_klass.new
11
+ end
12
+
13
+ def call(src = cmd, gem = nil)
14
+ tokens = tokenize(src)
15
+ token = tokens.shift
16
+ gem ||= Gem.factory(token)
17
+ tokens.each do |t|
18
+ dep = Gem.factory(t)
19
+ next unless dep
20
+ gem << dep
21
+ call(cmd(dep.name), dep)
22
+ end
23
+ gem
24
+ end
25
+
26
+ private def tokenize(src)
27
+ src = src.split(/\n\n/).first
28
+ src.split("\n").tap do |tokens|
29
+ tokens.map!(&:strip)
30
+ tokens.reject! { |token| token.match(/#{DEVELOPMENT}/) }
31
+ end
32
+ end
33
+
34
+ private def cmd(gem = @gem)
35
+ @cmd.call(gem)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,70 @@
1
+ module Lapidarius
2
+ class Gem
3
+ class KindError < ArgumentError; end
4
+
5
+ LEVEL_DEPTH = 5
6
+
7
+ def self.factory(name)
8
+ name.match(/Gem ([a-z0-9\-_]+)-(\d{1,2}\.\d{1,3}\.\d{1,2})/) do |m|
9
+ return new(name: m[1], version: m[2])
10
+ end
11
+ name.match(/([a-z0-9\-_]+) \(([0-9~<>=, \.]+)\)/) do |m|
12
+ return new(name: m[1], version: m[2])
13
+ end
14
+ end
15
+
16
+ attr_reader :name, :version, :deps
17
+
18
+ def initialize(name:, version:, deps: [])
19
+ @name = name
20
+ @version = version
21
+ @deps = deps
22
+ end
23
+
24
+ def <<(dep)
25
+ fail KindError, "#{dep.inspect} is not a valid gem" unless gem?(dep)
26
+ @deps << dep
27
+ end
28
+
29
+ def ==(gem)
30
+ return false unless gem?(gem)
31
+ gem.name == name && gem.version == version
32
+ end
33
+
34
+ def to_s(recursive: false)
35
+ return fullname unless recursive
36
+ fullname.tap do |s|
37
+ deps.each do |dep|
38
+ s << "\n"
39
+ s << indentation
40
+ s << dep.to_s(recursive: recursive)
41
+ end
42
+ end
43
+ end
44
+
45
+ def fullname
46
+ "#{name} (#{version})"
47
+ end
48
+
49
+ def deep_count
50
+ flatten_deps.size
51
+ end
52
+
53
+ protected def flatten_deps
54
+ deps.reduce(deps) do |acc, dep|
55
+ acc.concat dep.flatten_deps
56
+ end.tap do |deps|
57
+ deps.flatten!
58
+ deps.uniq!(&:name)
59
+ end
60
+ end
61
+
62
+ private def indentation
63
+ " " * (caller.size / LEVEL_DEPTH)
64
+ end
65
+
66
+ private def gem?(gem)
67
+ %i{name version deps}.all? { |msg| gem.respond_to?(msg) }
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,39 @@
1
+ module Lapidarius
2
+ class Renderer
3
+ class NoEntGemError< ArgumentError; end
4
+
5
+ def initialize(gem:, recursive: false)
6
+ fail NoEntGemError, "gem not found on this system!" unless gem
7
+ @gem = gem
8
+ @recursive = recursive
9
+ @out = []
10
+ end
11
+
12
+ def call(io = STDOUT)
13
+ io.puts out
14
+ end
15
+
16
+ def out
17
+ header
18
+ body
19
+ @out
20
+ end
21
+
22
+ private def header
23
+ @out << ("\n#{@gem.fullname}".ljust(28) << "#{@gem.deep_count}".rjust(3))
24
+ @out << hr
25
+ end
26
+
27
+ private def body
28
+ return if @gem.deps.empty?
29
+ @gem.deps.each do |dep|
30
+ @out << dep.to_s(recursive: @recursive)
31
+ end
32
+ @out << "\n"
33
+ end
34
+
35
+ private def hr
36
+ "#{"-" * 30}\n"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ require "stringio"
2
+
3
+ module Lapidarius
4
+ class UI
5
+ def initialize
6
+ @io = StringIO.new
7
+ end
8
+
9
+ def say(statement)
10
+ @io.puts statement
11
+ end
12
+
13
+ def out
14
+ @io.string.strip
15
+ end
16
+
17
+ def clear!
18
+ @io.reopen("")
19
+ end
20
+
21
+ def terminate_interaction(code = 0)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module Lapidarius
2
+ VERSION = "1.0.0"
3
+ end
data/tags ADDED
@@ -0,0 +1,33 @@
1
+ !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
2
+ !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
3
+ !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
4
+ !_TAG_PROGRAM_NAME Exuberant Ctags //
5
+ !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
6
+ !_TAG_PROGRAM_VERSION 5.8 //
7
+ << ./lib/lapidarius/gem.rb /^ def <<(dep)$/;" f class:Lapidarius
8
+ == ./lib/lapidarius/gem.rb /^ def ==(gem)$/;" f class:Lapidarius
9
+ Cutter ./lib/lapidarius/cutter.rb /^ class Cutter$/;" c class:Lapidarius
10
+ Cutter ./spec/mocks.rb /^ class Cutter$/;" c class:Lapidarius
11
+ Env ./lib/lapidarius/env.rb /^ module Env$/;" m class:Lapidarius
12
+ Gem ./lib/lapidarius/gem.rb /^ class Gem$/;" c class:Lapidarius
13
+ KindError ./lib/lapidarius/gem.rb /^ class KindError < ArgumentError; end$/;" c class:Lapidarius.Gem
14
+ Lapidarius ./lib/lapidarius/cutter.rb /^module Lapidarius$/;" m
15
+ Lapidarius ./lib/lapidarius/env.rb /^module Lapidarius$/;" m
16
+ Lapidarius ./lib/lapidarius/gem.rb /^module Lapidarius$/;" m
17
+ Lapidarius ./lib/lapidarius/renderer.rb /^module Lapidarius$/;" m
18
+ Lapidarius ./lib/lapidarius/version.rb /^module Lapidarius$/;" m
19
+ Lapidarius ./spec/mocks.rb /^module Lapidarius$/;" m
20
+ NoEntGemError ./lib/lapidarius/renderer.rb /^ class NoEntGemError< ArgumentError; end$/;" c class:Lapidarius.Renderer
21
+ Renderer ./lib/lapidarius/renderer.rb /^ class Renderer$/;" c class:Lapidarius
22
+ call ./lib/lapidarius/cutter.rb /^ def call(src = cmd, gem = nil)$/;" f class:Lapidarius.Cutter
23
+ call ./lib/lapidarius/renderer.rb /^ def call(io = STDOUT)$/;" f class:Lapidarius.Renderer
24
+ cmd ./spec/mocks.rb /^ def cmd(gem = @gem)$/;" f class:Lapidarius.Cutter
25
+ deps ./lib/lapidarius/gem.rb /^ def deps(env = :all)$/;" f class:Lapidarius
26
+ development? ./lib/lapidarius/gem.rb /^ def development?$/;" f
27
+ factory ./lib/lapidarius/gem.rb /^ def self.factory(name)$/;" F class:Lapidarius.Gem
28
+ initialize ./lib/lapidarius/cutter.rb /^ def initialize(gem:, include_dev: false)$/;" f class:Lapidarius.Cutter
29
+ initialize ./lib/lapidarius/gem.rb /^ def initialize(name:, version:, env: Env::RUNTIME, deps: [])$/;" f class:Lapidarius
30
+ initialize ./lib/lapidarius/renderer.rb /^ def initialize(gem)$/;" f class:Lapidarius.Renderer
31
+ out ./lib/lapidarius/renderer.rb /^ def out$/;" f class:Lapidarius.Renderer
32
+ runtime? ./lib/lapidarius/gem.rb /^ def runtime?$/;" f
33
+ to_s ./lib/lapidarius/gem.rb /^ def to_s$/;" f class:Lapidarius
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lapidarius
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - costajob
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-22 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.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
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
+ description:
56
+ email:
57
+ - costajob@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - README.md
66
+ - Rakefile
67
+ - bin/console
68
+ - bin/lapidarius
69
+ - bin/setup
70
+ - lapidarius.gemspec
71
+ - lib/lapidarius.rb
72
+ - lib/lapidarius/cli.rb
73
+ - lib/lapidarius/command.rb
74
+ - lib/lapidarius/cutter.rb
75
+ - lib/lapidarius/gem.rb
76
+ - lib/lapidarius/renderer.rb
77
+ - lib/lapidarius/ui.rb
78
+ - lib/lapidarius/version.rb
79
+ - tags
80
+ homepage: https://github.com/costajob/lapidarius
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 2.1.8
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.5.1
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: A tiny library to visualize and count gem dependencies recursively
104
+ test_files: []