rudisco 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: 96a8153da4c9000bc97fd6002722c56ab8b6a43b
4
+ data.tar.gz: 1f82e722e9ed26c5eb72457eca89e3a326b43842
5
+ SHA512:
6
+ metadata.gz: 266e7f221800b475a8af008b75556460f496b90c6579e04144cc37fa4e4a516c0695fea0b9622e5f9cbea67cb32e2a95162d0a0aeb1f0fb286aa1831cbb8a69d
7
+ data.tar.gz: 77fa868a5cdf7497bc4d4cdc93732ccacf683185215a7007ee2c5c41dcebc697b97b6c354d82fc6f942a0de94fb1549afd47d5c8fdf13eb983b103100db4adf0
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ source 'https://rubygems.org'
3
+
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'webmock', '~> 2.3.1', require: false
8
+ gem 'rspec', '~> 3.5.0', require: false
9
+ end
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ require 'bundler'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new
6
+ task default: :spec
7
+
8
+ path_to_rakes = File.join __dir__, 'rakefiles'
9
+ Dir.glob(File.join(path_to_rakes, '**/*')).each do |file|
10
+ import file if File.extname(file) == '.rake'
11
+ end
data/bin/rudisco ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ require File.join(__dir__, '..', 'sources', 'rudisco')
4
+
5
+ Rudisco::CLI::Application.start ARGV
Binary file
data/license.md ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) <2016> Kuzichev Michael
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ namespace 'Rudisco' do
3
+ desc "(long-term task) Starts multithread Rudisco::Gem table update"
4
+ task 'update' do
5
+ require File.join(__dir__, '..', 'sources', 'rudisco.rb')
6
+
7
+ puts "task Rudisco:update launched!"
8
+
9
+ Rudisco::Gem.surface_scanning
10
+ totally_updated, outdated =
11
+ 0, Rudisco::Gem.where(need_update: true).count
12
+
13
+ Rudisco::Gem.deep_scanning do |updated_count|
14
+ totally_updated += updated_count
15
+ print "Updated: #{totally_updated}/#{outdated}\r"
16
+ $stdout.flush
17
+ end
18
+
19
+ puts "task Rudisco:update completed the job."
20
+ end # task 'update'
21
+ end # namespace 'Rudisco'
data/readme.md ADDED
@@ -0,0 +1,106 @@
1
+ # Rudisco [![Build Status](https://travis-ci.org/Medvedu/rudisco.svg?branch=master)](https://travis-ci.org/Medvedu/rudisco)
2
+
3
+ ## Description
4
+
5
+ Gems local database (based on [Rubygems](https://rubygems.org)). Includes information about ~ 126000 gems.
6
+
7
+ Table _gems_ consist of next columns: _name, description, authors, version, license, sha, source_code_url_ and more. Full table structure described in gem.rb file.
8
+
9
+ ## Installation
10
+
11
+ ```shell
12
+ $ gem install rudisco
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Database usage example
18
+
19
+ ```ruby
20
+ gems = Rudisco::Gem # Sequel::Model
21
+
22
+ top = gems.where{ total_downloads > 50000000 }
23
+ .select(:name, :description, :source_code_url)
24
+
25
+ top.each do |record|
26
+ puts record[:name]
27
+ puts record[:description]
28
+ puts record[:source_code_url] if record[:source_code_url]
29
+ puts
30
+ end
31
+ ```
32
+
33
+ ### Simple search gems by selected phrase
34
+
35
+ ```ruby
36
+ phrase = 'rails'
37
+ gems = Rudisco::Gem.find_phrase(phrase)
38
+ .select(:name, :description)
39
+
40
+ gems.each do |record|
41
+ puts record[:name]
42
+ puts record[:description]
43
+ puts
44
+ end
45
+ ```
46
+
47
+ ### Open documentation and download gems
48
+
49
+ ```ruby
50
+ path_to_load = File.join(__dir__, '..', 'tmp')
51
+
52
+ sample = Rudisco::Gem.exclude(source_code_url: '').first
53
+ sample.action(:open_sources)
54
+ .action(:git_clone, path: path_to_load)
55
+
56
+ sample2 = Rudisco::Gem.limit(2)
57
+ sample2.action(:download, path: path_to_load)
58
+ ```
59
+ ### Update database
60
+
61
+ #### Throw CLI
62
+
63
+ ```shell
64
+ $ gem install rudisco
65
+ $ rudisco update
66
+ ```
67
+
68
+ #### By #deep_scanning call
69
+
70
+ ```ruby
71
+ require 'rudisco'
72
+
73
+ Rudisco::Gem.deep_scanning
74
+ ```
75
+
76
+ ## CLI
77
+
78
+ ![Alt text](./docs/images/image.jpg)
79
+
80
+ ### commands list
81
+
82
+ ```shell
83
+ $ rudisco clone GEM_NAME # Clones gem sources from git
84
+ $ rudisco download GEM_NAME # Downloads a gem
85
+ $ rudisco find PHRASE # Searches phrase in gem name or description
86
+ $ rudisco open GEM_NAME # Opens gem page on rubygems.org
87
+ $ rudisco show GEM_NAME # Shows detailed information about single gem
88
+ $ rudisco update # Updates database
89
+ ```
90
+
91
+ ## Todo
92
+
93
+ * Integrate with Github for better search results.
94
+ * Add CLI open (opens any url associated with gem in browser) & CLI statistic (database&program statistic) commands.
95
+ * Tests coverage.
96
+
97
+ ## Dependencies
98
+
99
+ * Ruby 2.1.0 or higher
100
+ * sqlite3 ~> 1.3.13
101
+ * sequel ~> 4.42.1
102
+
103
+ ## License
104
+ ----
105
+
106
+ Released under the MIT License. See the [LICENSE](./license.md) file for further details.
Binary file
@@ -0,0 +1,125 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Application < Thor
6
+ desc "find PHRASE", "Searches phrase in gem name or description"
7
+ method_option :limit,
8
+ :aliases => "-l",
9
+ :type => :numeric,
10
+ :default => 75,
11
+ :desc => "Limits search result. By default it shows 75 most popular gems",
12
+ :banner => "Search result limit (75 gems by default)"
13
+
14
+ def find(phrase)
15
+ records = Gem.find_phrase(phrase)
16
+ .order_by(Sequel.desc(:total_downloads))
17
+ .limit options[:limit]
18
+
19
+ Presentation::Find.new(records: records).show
20
+ end
21
+
22
+
23
+
24
+ desc "show GEM_NAME", "Shows detailed information about single gem"
25
+ def show(gem_name)
26
+ record = Gem.where(name: gem_name)
27
+ .first
28
+
29
+ Presentation::Show.new(record: record).show
30
+ end
31
+
32
+
33
+
34
+ desc "download GEM_NAME", "Downloads a gem"
35
+ method_option :path,
36
+ :aliases => "-p",
37
+ :type => :string,
38
+ :default => nil,
39
+ :desc => "Path where gem gonna be saved (default: ENV['HOME'])"
40
+
41
+ def download(gem_name)
42
+ record = Gem.where(name: gem_name).first
43
+
44
+ if record
45
+ path = File.expand_path(options[:path] || ENV['HOME'])
46
+
47
+ record.action :download, path: path
48
+ Presentation::Download.new(success: true, path: path).show
49
+ else
50
+ raise GemNotFound, gem_name
51
+ end
52
+
53
+ rescue Rudisco::Error => exception
54
+ Presentation::Download.new(success: false, exception: exception).show
55
+ end
56
+
57
+
58
+
59
+ desc "clone GEM_NAME", "Clones gem sources from git"
60
+ method_option :path,
61
+ :aliases => "-p",
62
+ :type => :string,
63
+ :default => nil,
64
+ :desc => "Path where gem gonna be saved (default: ENV['HOME'])"
65
+
66
+ def clone(gem_name)
67
+ record = Gem.where(name: gem_name).first
68
+
69
+ if record
70
+ path = File.expand_path(options[:path] || ENV['HOME'])
71
+
72
+ record.action :git_clone, path: path
73
+ Presentation::GitClone.new(success: true, path: path).show
74
+ else
75
+ raise GemNotFound, gem_name
76
+ end
77
+
78
+ rescue Rudisco::Helpers::NotAUrl
79
+ exception = GemWithoutGitSources.new gem_name
80
+ Presentation::GitClone.new(success: false, exception: exception).show
81
+
82
+ rescue Rudisco::Error => exception
83
+ Presentation::GitClone.new(success: false, exception: exception).show
84
+ end
85
+
86
+
87
+
88
+ desc "update", "Updates database"
89
+ def update
90
+ Rudisco::Gem.surface_scanning
91
+ outdated = Rudisco::Gem.where(need_update: true).count
92
+ cli_view = Presentation::Update.new(outdated: outdated)
93
+
94
+ summary = 0 and cli_view.show
95
+ if outdated > 0
96
+ Gem.deep_scanning do |updated|
97
+ summary += updated
98
+ cli_view.update(updated: summary)
99
+ end
100
+ cli_view.finished
101
+ end
102
+ end
103
+
104
+ desc "open GEM_NAME", "Opens gem page on rubygems.org"
105
+ def open(gem_name)
106
+ record = Gem.where(name: gem_name).first
107
+
108
+ if record
109
+ record.action :open_rubygems
110
+ else
111
+ raise GemNotFound, gem_name
112
+ end
113
+
114
+ rescue Rudisco::Error => exception
115
+ Presentation::Open.new(exception: exception).show
116
+ end
117
+
118
+ class GemNotFound < Error # no-doc
119
+ def initialize(name); super "Gem '#{name}' not found!" end; end
120
+
121
+ class GemWithoutGitSources < Error # no-doc
122
+ def initialize(name); super "Gem '#{name}' without git sources!" end; end
123
+ end # class Application
124
+ end # module CLI
125
+ end # module Rudisco
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Presentation::Download < Presentation
6
+ # @param [HASH] params
7
+ # @option params [String, NilClass] :path
8
+ # @option params [TrueClass, FalseClass] :success
9
+ # @option params [Exception, NilClass] :exception
10
+
11
+ def initialize(**params)
12
+ @success = params[:success]
13
+ @path = params[:path]
14
+ @exception = params[:exception]
15
+ end
16
+
17
+ def show # no-doc
18
+ report message: '', complete: '' do
19
+ if success
20
+ download_done
21
+ else
22
+ download_failed
23
+ end
24
+ end # report
25
+ end
26
+
27
+ private
28
+
29
+ def download_done # no-doc
30
+ header title: 'Download success', width: 80, align: 'center', bold: true
31
+
32
+ aligned "Gem was downloaded to #{path}", bold: true, width: 80,
33
+ align: 'center'
34
+ end
35
+
36
+ def download_failed # no-doc
37
+ header title: 'Download failed', width: 80, align: 'center', bold: true
38
+
39
+ aligned "Error message: #{exception.message}", bold: true, width: 80,
40
+ align: 'center'
41
+ end
42
+
43
+ # @return [String, NilClass]
44
+
45
+ attr_reader :path
46
+
47
+ # @return [TrueClass, FalseClass]
48
+
49
+ attr_reader :success
50
+
51
+ # @return [Exception, NilClass]
52
+
53
+ attr_reader :exception
54
+ end # class Presentation::Download
55
+ end # module CLI
56
+ end # module Rudisco
@@ -0,0 +1,87 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Presentation::Find < Presentation
6
+ def initialize(**params) # no-doc
7
+ @records = params[:records]
8
+ end
9
+
10
+ def show # no-doc
11
+ report message: '', complete: '' do
12
+ if records.count.zero?
13
+ nothing_was_found
14
+ else
15
+ show_results
16
+ end
17
+ end # report
18
+ end
19
+
20
+ private
21
+
22
+ # @return Array<Rudisco::Gem>
23
+
24
+ attr_reader :records
25
+
26
+ def nothing_was_found # no-doc
27
+ header title: 'Rudisco search results',
28
+ width: 80, align: 'center',
29
+ bold: true, timestamp: true
30
+
31
+ aligned "Nothing was found. Sorry.", bold: true, width: 80,
32
+ align: 'center'
33
+ end
34
+
35
+ def show_results # no-doc
36
+ header title: 'Rudisco search results',
37
+ width: 80, align: 'center',
38
+ bold: true, timestamp: true
39
+
40
+ table(border: true) do
41
+ row do
42
+ column '№', width: 3, align: 'center'
43
+ column 'Name', width: 17, align: 'center'
44
+ column 'Git', width: 3, align: 'center'
45
+ column 'Description', width: 46, align: 'center'
46
+ column 'DW (total)', width: 10, align: 'center'
47
+ end
48
+ records.each_with_index do |rec, index|
49
+ row do
50
+ column index
51
+ column rec.name
52
+ column source_code_helper(rec.source_code_url)
53
+ column clear_desc_helper(rec.description)
54
+ column rec.total_downloads
55
+ end
56
+ end
57
+ end # table
58
+ end
59
+
60
+ ##
61
+ # Returns copy of +description+ string, but without
62
+ # special symbols.
63
+ #
64
+ # @param [String] description
65
+ # Original string.
66
+ #
67
+ # @return [String]
68
+
69
+ def clear_desc_helper(description)
70
+ return "N/A" if description.nil? || description.empty?
71
+
72
+ tmp = description.dup
73
+ tmp = tmp.delete "#{1.chr}-#{31.chr}".split.join ' '
74
+
75
+ return tmp
76
+ end
77
+
78
+ def source_code_helper(source_code_url) # no-doc
79
+ if source_code_url.nil? || source_code_url.empty?
80
+ return "-"
81
+ else
82
+ return "+"
83
+ end
84
+ end
85
+ end # class Presentation::Find
86
+ end # module CLI
87
+ end # module Rudisco
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Presentation::GitClone < Presentation
6
+ # @param [HASH] params
7
+ # @option params [String, NilClass] :path
8
+ # @option params [TrueClass, FalseClass] :success
9
+ # @option params [Exception, NilClass] :exception
10
+
11
+ def initialize(**params)
12
+ @success = params[:success]
13
+ @path = params[:path]
14
+ @exception = params[:exception]
15
+ end
16
+
17
+ def show # no-doc
18
+ report message: '', complete: '' do
19
+ if success
20
+ git_clone_done
21
+ else
22
+ git_clone_failed
23
+ end
24
+ end # report
25
+ end
26
+
27
+ def git_clone_done # no-doc
28
+ header title: 'Gem was cloned!', width: 80, align: 'center',
29
+ bold: true
30
+
31
+ aligned "Path to folder #{path}", bold: true, width: 80, align: 'center'
32
+ end
33
+
34
+ def git_clone_failed # no-doc
35
+ header title: 'Gem clone failed.', width: 80, align: 'center',
36
+ bold: true
37
+
38
+ aligned "Error message: #{exception.message}", bold: true, width: 80,
39
+ align: 'center'
40
+ end
41
+
42
+ # @return [String, NilClass]
43
+
44
+ attr_reader :path
45
+
46
+ # @return [TrueClass, FalseClass]
47
+
48
+ attr_reader :success
49
+
50
+ # @return [Exception, NilClass]
51
+
52
+ attr_reader :exception
53
+
54
+ end # class Presentation::GitClone
55
+ end # module CLI
56
+ end # module Rudisco
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Presentation::Open < Presentation
6
+ def initialize(**params) # no-doc
7
+ @exception = params[:exception]
8
+ end
9
+
10
+ def show # no-doc
11
+ aligned "Error! Exception: #{exception.message}",
12
+ bold: true, width: 80, align: 'center'
13
+ end
14
+
15
+ private
16
+
17
+ # @return [Exception]
18
+
19
+ attr_reader :exception
20
+ end # Presentation::Open
21
+ end # module CLI
22
+ end # module Rudisco
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Presentation::Show < Presentation
6
+ def initialize(**params) # no-doc
7
+ @record = params[:record]
8
+ end
9
+
10
+ def show # no-doc
11
+ report message: '', complete: '' do
12
+ if record
13
+ show_detailed_gem_description
14
+ else
15
+ gem_not_found
16
+ end
17
+ end # report message
18
+ end
19
+
20
+ private
21
+
22
+ def gem_not_found # no-doc
23
+ aligned ""
24
+ aligned "Gem not found. Sorry.", bold: true, width: 80,
25
+ align: 'center'
26
+ aligned ""
27
+ end
28
+
29
+ def show_detailed_gem_description # no-doc
30
+ table(border: true, width: 80) do
31
+ row { column 'Description', width: 80, align: 'center' }
32
+ row { column record.description }
33
+ end
34
+
35
+ aligned ""
36
+
37
+ table(border: false, width: 80) do
38
+ row do
39
+ column 'Total downloads', width: 18, align: 'center'
40
+ column 'Version downloads', width: 18, align: 'center'
41
+ column 'Version', width: 18, align: 'center'
42
+ column 'License', width: 17, align: 'center'
43
+ end
44
+ row do
45
+ column record.total_downloads
46
+ column record.version_downloads
47
+ column record.version
48
+ column record.license
49
+ end
50
+ end # table
51
+
52
+ aligned ""
53
+
54
+ table(border: false, width: 80) do
55
+ row do
56
+ column 'wiki_url', width: 18, align: 'center'
57
+ column 'documentation_url', width: 18, align: 'center'
58
+ column 'mailing_list_url', width: 18, align: 'center'
59
+ column 'bug_tracker_url', width: 17, align: 'center'
60
+ end
61
+ row do
62
+ column url_helper(record.wiki_url)
63
+ column url_helper(record.documentation_url)
64
+ column url_helper(record.mailing_list_url)
65
+ column url_helper(record.bug_tracker_url)
66
+ end
67
+ end # table
68
+
69
+ aligned ""
70
+
71
+ table(border: false, width: 80) do
72
+ row do
73
+ column 'Authors', width: 20, align: 'center', padding: 2
74
+ column 'Sha', width: 57, align: 'center', padding: 10
75
+ end
76
+ row do
77
+ column record.authors
78
+ column record.sha
79
+ end
80
+ end # table
81
+ end
82
+
83
+ def url_helper(url) # no-doc
84
+ if url.nil? || url.empty?
85
+ return "no"
86
+ else
87
+ return "yes"
88
+ end
89
+ end
90
+
91
+ # @return [Rudisco::Gem]
92
+
93
+ attr_reader :record
94
+ end # class Presentation::Show
95
+ end # module CLI
96
+ end # module Rudisco
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Presentation::Update < Presentation
6
+ def initialize(**params) # no-doc
7
+ @outdated = params[:outdated]
8
+
9
+ self.formatter = 'progress'
10
+ end
11
+
12
+ def show # no-doc
13
+ header title: 'Update starting...', width: 80, align: 'center',
14
+ bold: true, timestamp: true
15
+
16
+ if outdated.zero?
17
+ aligned "Nothing to do!", width: 80, align: 'center'
18
+ else
19
+ aligned "#{outdated} records going to be added/updated.", width: 80,
20
+ align: 'center'
21
+ end
22
+ end
23
+
24
+ def update(**params) # no-doc
25
+ print "Updating...#{params[:updated]}/#{outdated}\r"
26
+ $stdout.flush
27
+ end
28
+
29
+ def finished # no-doc
30
+ aligned "Update finished! All records updated!", width: 80,
31
+ align: 'center'
32
+ end
33
+
34
+ private
35
+
36
+ # @return [Integer]
37
+
38
+ attr_reader :outdated
39
+ end # class Presentation::Update
40
+ end # module CLI
41
+ end # module Rudisco
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ module Rudisco
4
+ module CLI
5
+ class Presentation # no-doc
6
+ include CommandLineReporter
7
+
8
+ def initialize(**params) # no-doc
9
+ raise NotImplementedError, "Abstract class called!"
10
+ end
11
+
12
+ def show # no-doc
13
+ raise NotImplementedError, "Abstract method called!"
14
+ end
15
+ end # class Presentation
16
+ end # module CLI
17
+ end # module Rudisco