teuton-get 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +29 -0
- data/bin/teutonget +6 -0
- data/docs/commands.md +16 -0
- data/docs/get.md +50 -0
- data/docs/repo.md +68 -0
- data/docs/settings.md +40 -0
- data/lib/teuton-get/application/environment.rb +9 -0
- data/lib/teuton-get/application.rb +39 -0
- data/lib/teuton-get/cli.rb +89 -0
- data/lib/teuton-get/downloader.rb +71 -0
- data/lib/teuton-get/files/repos.ini +11 -0
- data/lib/teuton-get/files/tt-info.yaml +21 -0
- data/lib/teuton-get/reader/inifile_reader.rb +24 -0
- data/lib/teuton-get/reader/linux_environment_reader.rb +19 -0
- data/lib/teuton-get/reader/reader.rb +9 -0
- data/lib/teuton-get/reader/url_reader.rb +18 -0
- data/lib/teuton-get/reader/yaml_reader.rb +24 -0
- data/lib/teuton-get/repo/local_info.rb +71 -0
- data/lib/teuton-get/repo/local_repo.rb +70 -0
- data/lib/teuton-get/repo/repo_config.rb +92 -0
- data/lib/teuton-get/repo/repo_data.rb +126 -0
- data/lib/teuton-get/searcher/result.rb +21 -0
- data/lib/teuton-get/searcher.rb +142 -0
- data/lib/teuton-get/version.rb +6 -0
- data/lib/teuton-get/writer/file_writer.rb +19 -0
- data/lib/teuton-get/writer/null_writer.rb +15 -0
- data/lib/teuton-get/writer/terminal_writer.rb +20 -0
- data/lib/teuton-get/writer/writer.rb +9 -0
- data/lib/teuton-get.rb +45 -0
- metadata +149 -0
@@ -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,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,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
|
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
|