teuton-get 0.1.0

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.
@@ -0,0 +1,70 @@
1
+ require_relative "../application"
2
+ require_relative "../writer/file_writer"
3
+ require_relative "../writer/terminal_writer"
4
+
5
+ class LocalRepo
6
+ def initialize(args)
7
+ @repoindex_writer = args[:repoindex_writer]
8
+ @dev = args[:progress_writer]
9
+ end
10
+
11
+ def self.new_by_default
12
+ LocalRepo.new(
13
+ repoindex_writer: FileWriter.new,
14
+ progress_writer: TerminalWriter.new
15
+ )
16
+ end
17
+
18
+ def create(dirpath)
19
+ infofilename = Application::INFOFILENAME
20
+ infofiles = Dir.glob(File.join(dirpath, "**", infofilename))
21
+ return if infofiles.size.zero?
22
+
23
+ @dev.writeln "\n==> Creating repository", color: :light_yellow
24
+ data = read_files(infofiles)
25
+
26
+ filepath = File.join(dirpath, Application::INDEXFILENAME)
27
+ @repoindex_writer.open(filepath)
28
+ @repoindex_writer.write data.to_yaml
29
+ @repoindex_writer.close
30
+
31
+ @dev.writeln " Created file #{filepath} with #{data.keys.size} tests.", color: :white
32
+ true
33
+ end
34
+
35
+ private
36
+
37
+ def read_files(infofiles)
38
+ data = {}
39
+ infofiles.each do |filepath|
40
+ cleanpath = filepath
41
+ if cleanpath.start_with? "./"
42
+ # delete 2 chars at the begining. Example: "./"
43
+ cleanpath[0, 2] = ""
44
+ end
45
+ infodata = LocalInfo.new(@dev).read(cleanpath)
46
+ dirpath = File.dirname(cleanpath)
47
+ data[dirpath] = infodata
48
+ end
49
+ data
50
+ end
51
+
52
+ def copyfile(target, dest)
53
+ if File.exist? dest
54
+ @dev.write " WARN: exits file "
55
+ @dev.writeln dest, color: :light_yellow
56
+ return true
57
+ end
58
+ begin
59
+ FileUtils.cp(target, dest)
60
+ @dev.write "===> Created file "
61
+ @dev.writeln dest, color: :light_green
62
+ true
63
+ rescue => e
64
+ @dev.write " ERROR: Creating file "
65
+ @dev.writeln dest, color: :light_red
66
+ puts e
67
+ false
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,92 @@
1
+ require "fileutils"
2
+ require_relative "../application"
3
+ require_relative "../reader/inifile_reader"
4
+ require_relative "../writer/terminal_writer"
5
+
6
+ class RepoConfig
7
+ attr_reader :data
8
+
9
+ def initialize(args)
10
+ @reader = args[:config_reader]
11
+ @data = @reader.read
12
+ @dev = args[:progress_writer]
13
+
14
+ @config_dirpath = args[:config_dirpath] || ""
15
+ @config_filepath = File.join(@config_dirpath, Application::CONFIGFILE)
16
+ end
17
+
18
+ def self.new_by_default
19
+ config_filepath = Application.instance.get(:config_filepath)
20
+
21
+ RepoConfig.new(
22
+ config_reader: IniFileReader.new(config_filepath),
23
+ progress_writer: TerminalWriter.new,
24
+ config_dirpath: Application.instance.get(:config_dirpath)
25
+ )
26
+ end
27
+
28
+ def create
29
+ @dev.writeln "\n==> Creating configuration files", color: :light_yellow
30
+ create_dir
31
+ create_ini_file
32
+ end
33
+
34
+ def show_list
35
+ rows = []
36
+ rows << ["E", "NAME", "DESCRIPTION"]
37
+ rows << :separator
38
+
39
+ @data.each_pair do |key, value|
40
+ enable = "\u{2714}"
41
+ enable = " " unless value["enable"]
42
+ description = value["description"] || "?"
43
+ rows << [enable, key, description]
44
+ end
45
+ @dev.writeln "Repository list"
46
+ @dev.write_table(rows)
47
+ @dev.write "Config: "
48
+ @dev.writeln "#{@reader.source}\n", color: :white
49
+ end
50
+
51
+ private
52
+
53
+ def create_dir
54
+ dirpath = @config_dirpath
55
+ if Dir.exist? dirpath
56
+ @dev.write " \u{2716} Exists dir! : "
57
+ @dev.writeln dirpath, color: :yellow
58
+ else
59
+ begin
60
+ FileUtils.mkdir_p(dirpath)
61
+ @dev.write " \u{2714} Create dir : "
62
+ @dev.writeln dirpath, color: :green
63
+ rescue => e
64
+ @dev.write " \u{2716} Create dir ERROR: "
65
+ @dev.writeln dirpath, color: :red
66
+ puts e
67
+ end
68
+ end
69
+ end
70
+
71
+ def create_ini_file
72
+ src = File.join(File.dirname(__FILE__), "..", "files", Application::CONFIGFILE)
73
+ copyfile(src, @config_filepath)
74
+ end
75
+
76
+ def copyfile(target, dest)
77
+ if File.exist? dest
78
+ @dev.write " \u{2716} Exists file! : "
79
+ @dev.writeln dest, color: :yellow
80
+ return true
81
+ end
82
+ begin
83
+ FileUtils.cp(target, dest)
84
+ @dev.write " \u{2714} Create file : "
85
+ @dev.writeln dest, color: :green
86
+ rescue => e
87
+ @dev.write " \u{2716} Create file ERROR: "
88
+ @dev.writeln dest, color: :red
89
+ puts e
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,126 @@
1
+ require "yaml"
2
+ require_relative "../application"
3
+ require_relative "../reader/url_reader"
4
+ require_relative "../reader/inifile_reader"
5
+ require_relative "../reader/yaml_reader"
6
+
7
+ class RepoData
8
+ attr_reader :data
9
+
10
+ def initialize(args)
11
+ @reader = args[:config_reader]
12
+ @data = @reader.read
13
+ @dev = args[:progress_writer]
14
+ @cache_dirpath = args[:cache_dirpath]
15
+ end
16
+
17
+ def self.new_by_default
18
+ config_filepath = Application.instance.get(:config_filepath)
19
+ RepoData.new(
20
+ config_reader: IniFileReader.new(config_filepath),
21
+ progress_writer: TerminalWriter.new,
22
+ cache_dirpath: Application.instance.get(:cache_dirpath)
23
+ )
24
+ end
25
+
26
+ def refresh
27
+ @database = {}
28
+ dirpath = @cache_dirpath
29
+ FileUtils.rm_r(dirpath) if Dir.exist? dirpath
30
+
31
+ @dev.writeln "\n==> Refreshing active repos", color: :light_yellow
32
+ @data.keys.sort.each do |key|
33
+ refresh_repo key
34
+ end
35
+ save_database
36
+ end
37
+
38
+ def get(test_id)
39
+ reponame, id = test_id.split(Application::SEPARATOR)
40
+ database = YamlReader.new.read(database_filename)
41
+ return {} if database[reponame].nil?
42
+ database[reponame][id]
43
+ end
44
+
45
+ def show_testinfo(item)
46
+ return unless item
47
+ @dev.writeln ""
48
+ ["name", "author", "date", "desc"].each do |key|
49
+ @dev.write "#{key.ljust(7)} : ", color: :white
50
+ @dev.writeln item[key].to_s
51
+ end
52
+ ["tags", "files"].each do |key|
53
+ next if item[key].nil?
54
+ @dev.write "#{key.ljust(7)} : ", color: :white
55
+ @dev.writeln item[key].join(", ")
56
+ end
57
+ end
58
+
59
+ def database_filename
60
+ # REVISE: Used by teutonget search... replace by #get()
61
+ File.join(@cache_dirpath, "database.yaml")
62
+ end
63
+
64
+ private
65
+
66
+ def refresh_repo(reponame)
67
+ unless enabled? reponame
68
+ @dev.writeln " \u{2716} Skiping repo #{reponame}"
69
+ return false
70
+ end
71
+ dirpath = File.join(@cache_dirpath)
72
+ ok1 = create_dir(dirpath)
73
+ ok2 = get_database(reponame)
74
+
75
+ @dev.writeln " \u{2714} Repo #{reponame} (#{ok2.size} tests)"
76
+
77
+ true && ok1 && ok2
78
+ end
79
+
80
+ def enabled?(reponame)
81
+ @data[reponame]["enable"] == true
82
+ end
83
+
84
+ def create_dir(dirpath)
85
+ unless Dir.exist? dirpath
86
+ begin
87
+ FileUtils.mkdir_p(dirpath)
88
+ return true
89
+ rescue => e
90
+ @dev.write "* Create dir ERROR => "
91
+ @dev.writeln dirpath, color: :red
92
+ puts e
93
+ return false
94
+ end
95
+ end
96
+ false
97
+ end
98
+
99
+ def get_database(reponame)
100
+ data = @data[reponame]
101
+
102
+ @database[reponame] = if data["URL"].start_with? "http"
103
+ get_remote_database(data["URL"])
104
+ else
105
+ get_local_database(data["URL"])
106
+ end
107
+ end
108
+
109
+ def get_local_database(dirpath)
110
+ filepath = File.join(dirpath, Application::INDEXFILENAME)
111
+ @reader.read(filepath)
112
+ end
113
+
114
+ def get_remote_database(url_repo)
115
+ url_file = "#{url_repo}/#{Application::INDEXFILENAME}"
116
+ content_page = URLReader.new(url_file).read
117
+ YAML.safe_load(
118
+ content_page,
119
+ permitted_classes: [Array, Date, Hash, Symbol]
120
+ )
121
+ end
122
+
123
+ def save_database
124
+ File.write(database_filename, @database.to_yaml)
125
+ end
126
+ end
@@ -0,0 +1,21 @@
1
+ require_relative "../application"
2
+
3
+ class Result
4
+ attr_accessor :score
5
+ attr_reader :reponame
6
+ attr_reader :testname
7
+
8
+ def initialize(args)
9
+ @score = args[:score] || 0
10
+ @reponame = args[:reponame] || "???"
11
+ @testname = args[:testname] || "???"
12
+ end
13
+
14
+ def id
15
+ "#{reponame}#{Application::SEPARATOR}#{testname}"
16
+ end
17
+
18
+ def to_h
19
+ {score: @score, id: id, reponame: @reponame, testname: @testname}
20
+ end
21
+ end
@@ -0,0 +1,142 @@
1
+ require_relative "application"
2
+ require_relative "reader/yaml_reader"
3
+ require_relative "repo/repo_data"
4
+ require_relative "searcher/result"
5
+ require_relative "writer/terminal_writer"
6
+
7
+ class Searcher
8
+ def initialize(args)
9
+ @dev = args[:writer]
10
+
11
+ @repodata = args[:repodata]
12
+ filename = @repodata.database_filename
13
+
14
+ @reader = args[:reader]
15
+ @database = @reader.read(filename)
16
+
17
+ @results = {}
18
+ end
19
+
20
+ def self.new_by_default
21
+ Searcher.new(
22
+ writer: TerminalWriter.new,
23
+ repodata: RepoData.new_by_default,
24
+ reader: YamlReader.new
25
+ )
26
+ end
27
+
28
+ def get(input)
29
+ reponame_filter, filters = parse_input(input)
30
+ search_inside(reponame_filter, filters)
31
+ end
32
+
33
+ def show(result)
34
+ @results.each do |i|
35
+ @dev.write "(x#{i[:score]}) ", color: :white
36
+ @dev.writeln "#{i[:reponame]}#{Application::SEPARATOR}#{i[:testname]}"
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def parse_input(input)
43
+ reponame_filter = :all
44
+ filter = :all
45
+ options = input.split(Application::SEPARATOR)
46
+ if options.size == 1
47
+ reponame_filter = :all
48
+ filter = options[0]
49
+ elsif options[0] == ""
50
+ reponame_filter = :all
51
+ filter = options[1]
52
+ elsif options.size == 2
53
+ reponame_filter = options[0]
54
+ filter = options[1]
55
+ end
56
+ reponame_filter = :all if reponame_filter == "ALL"
57
+ filters = if filter == "ALL"
58
+ :all
59
+ else
60
+ filter.split(",")
61
+ end
62
+ [reponame_filter, filters]
63
+ end
64
+
65
+ def search_inside(reponame_filter, filters)
66
+ @results = {}
67
+ if reponame_filter == :all
68
+ @database.keys.each { |reponame| search_inside_repo(reponame, filters) }
69
+ else
70
+ @database.keys.each do |reponame|
71
+ search_inside_repo(reponame, filters) if reponame.include? reponame_filter
72
+ end
73
+ end
74
+ sort_results
75
+ end
76
+
77
+ def search_inside_repo(reponame, filters)
78
+ return if reponame != :all && @database[reponame].nil?
79
+
80
+ @database[reponame].each do |testname, data|
81
+ result = Result.new(
82
+ score: 0,
83
+ reponame: reponame,
84
+ testname: testname
85
+ )
86
+ if filters == :all
87
+ add_result(result)
88
+ next
89
+ end
90
+ score = 0
91
+ filters.each do |filter|
92
+ score += evaluate_test(
93
+ testname: testname,
94
+ data: data,
95
+ filter: filter
96
+ )
97
+ if score > 0
98
+ result.score = score
99
+ add_result result
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def evaluate_test(args)
106
+ testname = args[:testname]
107
+ data = args[:data]
108
+ filter = args[:filter]
109
+
110
+ score = 0
111
+ data.each_pair do |key, value|
112
+ if value.instance_of? String
113
+ score += 1 if value.downcase.include? filter
114
+ elsif value.instance_of? Date
115
+ score += 1 if value.to_s.include? filter
116
+ elsif value.instance_of? Array
117
+ score += 1 if value.include? filter
118
+ end
119
+ end
120
+ score += 1 if testname.include? filter
121
+ score
122
+ end
123
+
124
+ def add_result(result)
125
+ key = result.id
126
+ if @results[key].nil?
127
+ @results[key] = result
128
+ return
129
+ end
130
+ @results[key].score += result.score
131
+ end
132
+
133
+ def sort_results
134
+ results = []
135
+ @results.each_pair { |key, value| results += [value.to_h] }
136
+
137
+ results.sort_by! do |i|
138
+ [(Application::MAGICNUMBER - i[:score]), i[:id]]
139
+ end
140
+ @results = results
141
+ end
142
+ end
@@ -0,0 +1,6 @@
1
+ module Version
2
+ NAME = "teuton-get"
3
+ EXECUTABLE = "teutonget"
4
+ VERSION = "0.1.0"
5
+ HOMEPAGE = "https://github.com/teuton-software/#{NAME}"
6
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "writer"
2
+
3
+ class FileWriter < Writer
4
+ def open(filepath)
5
+ @file = File.open(filepath, "w")
6
+ end
7
+
8
+ def write(text)
9
+ @file.write text
10
+ end
11
+
12
+ def writeln(text)
13
+ @file.write text
14
+ end
15
+
16
+ def close
17
+ @file.close
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "writer"
2
+
3
+ class NullWriter < Writer
4
+ def write(text = "", args = {})
5
+ # Nothing
6
+ end
7
+
8
+ def writeln(text = "", args = {})
9
+ # Nothing
10
+ end
11
+
12
+ def write_table(rows)
13
+ # Nothing
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require "colorize"
2
+ require "tty-table"
3
+ require_relative "writer"
4
+
5
+ class TerminalWriter < Writer
6
+ def write(text = "", args = {})
7
+ color = args[:color] || :silver
8
+ print text.colorize(color)
9
+ end
10
+
11
+ def writeln(text = "", args = {})
12
+ write("#{text}\n", args)
13
+ end
14
+
15
+ def write_table(rows)
16
+ table = TTY::Table.new(rows)
17
+ # puts table.render(:basic)
18
+ puts table.render(:ascii)
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ class Writer
2
+ def write(data)
3
+ raise "Define method"
4
+ end
5
+
6
+ def writeln(data)
7
+ raise "Define method"
8
+ end
9
+ end
data/lib/teuton-get.rb ADDED
@@ -0,0 +1,45 @@
1
+ require_relative "teuton-get/repo/local_info"
2
+ require_relative "teuton-get/repo/local_repo"
3
+ require_relative "teuton-get/repo/repo_config"
4
+ require_relative "teuton-get/repo/repo_data"
5
+ require_relative "teuton-get/searcher"
6
+ require_relative "teuton-get/downloader"
7
+
8
+ module TeutonGet
9
+ def self.create_info(testpath)
10
+ LocalInfo.new.user_create(testpath)
11
+ end
12
+
13
+ def self.create_repo(dirpath)
14
+ LocalRepo.new_by_default.create(dirpath)
15
+ end
16
+
17
+ def self.init
18
+ RepoConfig.new_by_default.create
19
+ refresh # Auto repo refresh
20
+ end
21
+
22
+ def self.refresh
23
+ RepoData.new_by_default.refresh
24
+ end
25
+
26
+ def self.show_repo_list
27
+ RepoConfig.new_by_default.show_list
28
+ end
29
+
30
+ def self.show_info(test_id)
31
+ repo_data = RepoData.new_by_default
32
+ info = repo_data.get(test_id)
33
+ repo_data.show_testinfo(info) unless info == {}
34
+ end
35
+
36
+ def self.search(filter)
37
+ searcher = Searcher.new_by_default
38
+ result = searcher.get(filter)
39
+ searcher.show(result)
40
+ end
41
+
42
+ def self.download(test_id)
43
+ Downloader.new.run(test_id)
44
+ end
45
+ end