skap 1.0.2 → 1.0.3
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 +4 -4
- data/lib/skap/cli/help.rb +39 -40
- data/lib/skap/cli/init.rb +14 -15
- data/lib/skap/cli/sources.rb +46 -47
- data/lib/skap/cli/version.rb +7 -8
- data/lib/skap/cli/works.rb +134 -135
- data/lib/skap/cli.rb +14 -15
- data/lib/skap/command.rb +19 -20
- data/lib/skap/files/menu.rb +6 -9
- data/lib/skap/files/sources.rb +29 -32
- data/lib/skap/files/versions.rb +39 -42
- data/lib/skap/string_utils.rb +38 -39
- data/lib/skap/version.rb +1 -1
- data/lib/skap/yaml_file.rb +18 -19
- data/lib/skap.rb +7 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64c306b147d5300884174c3d2a4d6c6c51aec457b254304ec8d5d5df1be6b5f4
|
4
|
+
data.tar.gz: a652962929effff42642bcbe13f35c06c6cd787827377ce2e98d8c1909d0e23f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d70210fe51ee5f0fa6f88683679f6995b2d39c07065be89a4bc16499658339e98313940e08b3d4814e1699fab9c043f8bf1ec3e834c162155e535562e145711b
|
7
|
+
data.tar.gz: ecfca637dbb0deb6f68c90e4dfcbffc08a4fc619bd87f7df1d754e7846935a730844c45ea6da7177dec3349912bdd34360b6b737dd39b41253835a09577c1b1a
|
data/lib/skap/cli/help.rb
CHANGED
@@ -1,58 +1,57 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# CLI command with help message.
|
4
|
+
module Skap::CLI::Help
|
5
|
+
include Skap::Command
|
6
|
+
extend self
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# @return [void]
|
9
|
+
def start
|
10
|
+
menu = Skap::Files::Menu.new
|
11
11
|
|
12
|
-
|
12
|
+
puts "Usage:", ""
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
private
|
14
|
+
show_menu(menu, $DEFAULT_OUTPUT.winsize.last)
|
15
|
+
end
|
18
16
|
|
19
|
-
|
20
|
-
# @param indent [String]
|
21
|
-
# @param max_width [Integer]
|
22
|
-
# @return [void]
|
23
|
-
def output_menu_item_text(text, indent, max_width)
|
24
|
-
res = []
|
17
|
+
private
|
25
18
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
19
|
+
# @param text [String]
|
20
|
+
# @param indent [String]
|
21
|
+
# @param max_width [Integer]
|
22
|
+
# @return [void]
|
23
|
+
def output_menu_item_text(text, indent, max_width)
|
24
|
+
res = []
|
31
25
|
|
32
|
-
|
26
|
+
if text.is_a?(Array)
|
27
|
+
text.each { |paragraph| res += Skap::StringUtils.break_by_words(paragraph, max_width) }
|
28
|
+
else
|
29
|
+
res += Skap::StringUtils.break_by_words(text, max_width)
|
33
30
|
end
|
34
31
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
32
|
+
res.each { |line| puts "#{indent}#{line}" }
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param menu [Files::Menu]
|
36
|
+
# @param width [Integer]
|
37
|
+
# @return [void]
|
38
|
+
def show_menu(menu, width) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
39
|
+
section_indent = " " * 4
|
40
|
+
command_indent = " " * 8
|
41
|
+
within_section = width - 4
|
42
|
+
within_command = width - 8
|
43
43
|
|
44
|
-
|
45
|
-
|
44
|
+
menu.each do |item|
|
45
|
+
puts item["cmd"]
|
46
46
|
|
47
|
-
|
47
|
+
output_menu_item_text(item["text"], section_indent, within_section) if item.key?("text")
|
48
48
|
|
49
|
-
|
49
|
+
next unless item.key?("children")
|
50
50
|
|
51
|
-
|
52
|
-
|
51
|
+
item["children"].each do |subitem|
|
52
|
+
[*subitem["cmd"]].each { |cmd| puts "#{section_indent}#{cmd}" }
|
53
53
|
|
54
|
-
|
55
|
-
end
|
54
|
+
output_menu_item_text(subitem["text"], command_indent, within_command)
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
data/lib/skap/cli/init.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# CLI command for repository initialization.
|
4
|
+
module Skap::CLI::Init
|
5
|
+
include Skap::Command
|
6
|
+
extend self
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
# @param dir [String]
|
9
|
+
# @param args [Array<String>]
|
10
|
+
# @return [void]
|
11
|
+
def start(dir, args)
|
12
|
+
assert_empty_options(args)
|
13
13
|
|
14
|
-
|
14
|
+
FileUtils.mkdir_p(dir)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
shell("git init", dir:)
|
17
|
+
shell("echo '---\n' > #{Skap::Files::Sources.file_name}", dir:)
|
18
|
+
shell("echo '---\n' > #{Skap::Files::Versions.file_name}", dir:)
|
19
19
|
|
20
|
-
|
21
|
-
end
|
20
|
+
puts "Git repo initialized in #{dir}"
|
22
21
|
end
|
23
22
|
end
|
data/lib/skap/cli/sources.rb
CHANGED
@@ -1,62 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
3
|
+
# CLI command for managing sources list.
|
4
|
+
module Skap::CLI::Sources
|
5
|
+
include Skap::Command
|
6
|
+
extend self
|
7
|
+
|
8
|
+
# @param command [String]
|
9
|
+
# @param args [Array<String>]
|
10
|
+
# @return [void]
|
11
|
+
def start(command, args)
|
12
|
+
assert_cwd
|
13
|
+
|
14
|
+
case command
|
15
|
+
when "add" then add(*args)
|
16
|
+
when "delete" then delete(*args)
|
17
|
+
when "update" then update(*args)
|
18
|
+
else
|
19
|
+
raise ArgumentError, "Unknown command: #{command}"
|
21
20
|
end
|
21
|
+
end
|
22
22
|
|
23
|
-
|
23
|
+
private
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
# @param dir [String]
|
26
|
+
# @param repo [String]
|
27
|
+
# @param branch [String]
|
28
|
+
# @param rest [Array<String>]
|
29
|
+
# @return [void]
|
30
|
+
def add(dir, repo, branch, *rest)
|
31
|
+
assert_empty_options(rest)
|
32
32
|
|
33
|
-
|
33
|
+
return unless shell("git submodule add -b #{branch} --depth 3 -- #{repo} #{dir}")
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
Skap::Files::Sources.new.add_source(dir)
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
# @param dir [String]
|
39
|
+
# @param rest [Array<String>]
|
40
|
+
# @return [void]
|
41
|
+
def delete(dir, *rest)
|
42
|
+
assert_empty_options(rest)
|
43
43
|
|
44
|
-
|
44
|
+
shell("git submodule deinit -f -- #{dir} && git rm -f #{dir} && rm -rf .git/modules/#{dir}")
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
Skap::Files::Sources.new.delete_source(dir)
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
# @param dirs [Array<String>]
|
50
|
+
# @return [void]
|
51
|
+
def update(*dirs)
|
52
|
+
path_arg = dirs.empty? ? "" : "-- #{dirs.join(" ")}"
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
commands = [
|
55
|
+
"git submodule init",
|
56
|
+
"git submodule update --checkout --single-branch --recursive #{path_arg}",
|
57
|
+
]
|
58
58
|
|
59
|
-
|
60
|
-
end
|
59
|
+
shell(commands.join(" && "))
|
61
60
|
end
|
62
61
|
end
|
data/lib/skap/cli/version.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# CLI command for showing Skap version.
|
4
|
+
module Skap::CLI::Version
|
5
|
+
include Skap::Command
|
6
|
+
extend self
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
8
|
+
# @return [void]
|
9
|
+
def start
|
10
|
+
puts "Skap, v#{Skap::VERSION}"
|
12
11
|
end
|
13
12
|
end
|
data/lib/skap/cli/works.rb
CHANGED
@@ -1,175 +1,174 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
3
|
+
# CLI command for managing works (files based on sources).
|
4
|
+
module Skap::CLI::Works
|
5
|
+
include Skap::Command
|
6
|
+
extend self
|
7
|
+
|
8
|
+
# @param command [String]
|
9
|
+
# @param args [Array<String>]
|
10
|
+
# @return [void]
|
11
|
+
def start(command, args) # rubocop:disable Metrics/MethodLength
|
12
|
+
assert_cwd
|
13
|
+
|
14
|
+
case command
|
15
|
+
when "covered" then covered(*args)
|
16
|
+
when "ignored" then ignored(*args)
|
17
|
+
when "publish" then publish(*args)
|
18
|
+
when "outdated" then outdated(*args)
|
19
|
+
when "uncovered" then uncovered(*args)
|
20
|
+
when "unknown" then unknown(*args)
|
21
|
+
else
|
22
|
+
raise ArgumentError, "Unknown command: #{command}"
|
24
23
|
end
|
24
|
+
end
|
25
25
|
|
26
|
-
|
26
|
+
private
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
28
|
+
# @param path_patterns_as_hash [Hash<String, Array<String>>]
|
29
|
+
# @return [Array<String>]
|
30
|
+
def collect_files(path_patterns_as_hash)
|
31
|
+
flatten_path_patterns(path_patterns_as_hash).flat_map do |path_pattern|
|
32
|
+
find_files_by_pattern(path_pattern)
|
34
33
|
end
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
shell("git rev-parse HEAD -- #{file}", dir:).split("\n").first
|
42
|
-
end
|
36
|
+
# @param path [String]
|
37
|
+
# @return [String]
|
38
|
+
def commit_sha(path)
|
39
|
+
dir, file = File.split(path)
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
def covered(*dirs)
|
47
|
-
sources = Files::Sources.new.extract("indexed", dir_names_without_slash(dirs))
|
41
|
+
shell("git rev-parse HEAD -- #{file}", dir:).split("\n").first
|
42
|
+
end
|
48
43
|
|
49
|
-
|
50
|
-
|
44
|
+
# @param dirs [Array<String>]
|
45
|
+
# @return [void]
|
46
|
+
def covered(*dirs)
|
47
|
+
sources = Skap::Files::Sources.new.extract("indexed", dir_names_without_slash(dirs))
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
def dir_names_with_slash(dirs)
|
55
|
-
dirs.map { |x| x.end_with?("/") ? x : "#{x}/" }
|
56
|
-
end
|
49
|
+
puts (Skap::Files::Versions.new.covered_sources & collect_files(sources)).sort
|
50
|
+
end
|
57
51
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
52
|
+
# @param dirs [Array<String>]
|
53
|
+
# @return [Array<String>]
|
54
|
+
def dir_names_with_slash(dirs)
|
55
|
+
dirs.map { |x| x.end_with?("/") ? x : "#{x}/" }
|
56
|
+
end
|
63
57
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
raise ArgumentError, "No files found for path pattern \"#{path_pattern}\"" if result.empty?
|
58
|
+
# @param dirs [Array<String>]
|
59
|
+
# @return [Array<String>]
|
60
|
+
def dir_names_without_slash(dirs)
|
61
|
+
dirs.map { |x| x.end_with?("/") ? x.chop : x }
|
62
|
+
end
|
70
63
|
|
71
|
-
|
72
|
-
|
73
|
-
|
64
|
+
# @param path_pattern [String]
|
65
|
+
# @return [Array<String>]
|
66
|
+
def find_files_by_pattern(path_pattern)
|
67
|
+
if path_pattern.include?("*")
|
68
|
+
result = Dir.glob(path_pattern, base: CURRENT_DIR)
|
69
|
+
raise ArgumentError, "No files found for path pattern \"#{path_pattern}\"" if result.empty?
|
74
70
|
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
result
|
72
|
+
else
|
73
|
+
raise ArgumentError, "File \"#{path_pattern}\" doesn't exist" if !File.exist?(path_pattern)
|
78
74
|
|
79
|
-
|
80
|
-
# @return [Array<String>]
|
81
|
-
def flatten_path_patterns(hash)
|
82
|
-
hash.flat_map { |dir, paths| paths.map { |x| File.join(dir, x) } }
|
75
|
+
path_pattern
|
83
76
|
end
|
77
|
+
end
|
84
78
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
79
|
+
# @param hash [Hash<String, Array<String>>]
|
80
|
+
# @return [Array<String>]
|
81
|
+
def flatten_path_patterns(hash)
|
82
|
+
hash.flat_map { |dir, paths| paths.map { |x| File.join(dir, x) } }
|
83
|
+
end
|
89
84
|
|
90
|
-
|
91
|
-
|
85
|
+
# @param dirs [Array<String>]
|
86
|
+
# @return [void]
|
87
|
+
def ignored(*dirs)
|
88
|
+
sources = Skap::Files::Sources.new.extract("ignored", dir_names_without_slash(dirs))
|
92
89
|
|
93
|
-
|
94
|
-
|
95
|
-
def outdated(*dirs)
|
96
|
-
dirs = dir_names_with_slash(dirs)
|
90
|
+
puts collect_files(sources).sort
|
91
|
+
end
|
97
92
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
93
|
+
# @param dirs [Array<String>]
|
94
|
+
# @return [void]
|
95
|
+
def outdated(*dirs)
|
96
|
+
dirs = dir_names_with_slash(dirs)
|
102
97
|
|
103
|
-
|
104
|
-
|
98
|
+
outdated_documents =
|
99
|
+
Skap::Files::Versions.new.outdated_documents do |source_path|
|
100
|
+
dirs.empty? || source_path.start_with?(*dirs) ? commit_sha(source_path) : nil
|
105
101
|
end
|
106
|
-
end
|
107
102
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
excluded_file_paths = sources_paths.select { |x| x.start_with?("-") }
|
113
|
-
added_file_paths = sources_paths - excluded_file_paths
|
103
|
+
outdated_documents.each do |(doc_path, outdated_sources)|
|
104
|
+
puts doc_path, outdated_sources.map { |x| "* #{x}" }, ""
|
105
|
+
end
|
106
|
+
end
|
114
107
|
|
115
|
-
|
108
|
+
# @param document_path [String]
|
109
|
+
# @param sources_paths [Array<String>]
|
110
|
+
# @return [void]
|
111
|
+
def publish(document_path, *sources_paths)
|
112
|
+
excluded_file_paths = sources_paths.select { |x| x.start_with?("-") }
|
113
|
+
added_file_paths = sources_paths - excluded_file_paths
|
116
114
|
|
117
|
-
|
118
|
-
doc = versions.find_document(document_path) || {}
|
115
|
+
excluded_file_paths.map! { |x| x[1..] }
|
119
116
|
|
120
|
-
|
121
|
-
|
117
|
+
versions = Skap::Files::Versions.new
|
118
|
+
doc = versions.find_document(document_path) || {}
|
122
119
|
|
123
|
-
|
124
|
-
|
120
|
+
update_document_info(doc, added_file_paths, excluded_file_paths)
|
121
|
+
versions.add_document(document_path, doc)
|
125
122
|
|
126
|
-
|
127
|
-
|
128
|
-
def trackable_files(sources_data)
|
129
|
-
sources_data
|
130
|
-
.extract("file-extensions")
|
131
|
-
.transform_values { |v| v.join(",") }
|
132
|
-
.reduce([]) { |a, (dir, ext)| a + Dir.glob("#{dir}/**/*.{#{ext}}") }
|
133
|
-
end
|
123
|
+
puts "Version updated for #{document_path} in #{Skap::Files::Versions.file_name}"
|
124
|
+
end
|
134
125
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
126
|
+
# @param path_patterns_as_hash [Hash<String, Hash<String, Array<String>>>]
|
127
|
+
# @return [Array<String>]
|
128
|
+
def trackable_files(sources_data)
|
129
|
+
sources_data
|
130
|
+
.extract("file-extensions")
|
131
|
+
.transform_values { |v| v.join(",") }
|
132
|
+
.reduce([]) { |a, (dir, ext)| a + Dir.glob("#{dir}/**/*.{#{ext}}") }
|
133
|
+
end
|
139
134
|
|
140
|
-
|
141
|
-
|
135
|
+
# @param dirs [Array<String>]
|
136
|
+
# @return [void]
|
137
|
+
def uncovered(*dirs)
|
138
|
+
sources = Skap::Files::Sources.new.extract("indexed", dir_names_without_slash(dirs))
|
142
139
|
|
143
|
-
|
144
|
-
|
145
|
-
def unknown(*dirs)
|
146
|
-
sources_data = Files::Sources.new
|
147
|
-
sources_data.select_directories!(dir_names_without_slash(dirs)) if !dirs.empty?
|
140
|
+
puts (collect_files(sources) - Skap::Files::Versions.new.covered_sources.to_a).sort
|
141
|
+
end
|
148
142
|
|
149
|
-
|
150
|
-
|
151
|
-
|
143
|
+
# @param dirs [Array<String>]
|
144
|
+
# @return [void]
|
145
|
+
def unknown(*dirs)
|
146
|
+
sources_data = Skap::Files::Sources.new
|
147
|
+
sources_data.select_directories!(dir_names_without_slash(dirs)) if !dirs.empty?
|
152
148
|
|
153
|
-
|
154
|
-
|
149
|
+
all_files = trackable_files(sources_data)
|
150
|
+
ignored_files = collect_files(sources_data.extract("ignored"))
|
151
|
+
indexed_files = collect_files(sources_data.extract("indexed"))
|
155
152
|
|
156
|
-
|
157
|
-
|
158
|
-
# @param excluded_file_paths [Array<String>]
|
159
|
-
# @return [void]
|
160
|
-
def update_document_info(doc, added_file_paths, excluded_file_paths)
|
161
|
-
today = Time.now.strftime("%F")
|
153
|
+
puts (all_files - ignored_files - indexed_files).sort
|
154
|
+
end
|
162
155
|
|
163
|
-
|
164
|
-
|
156
|
+
# @param doc [Hash<String, Object>]
|
157
|
+
# @param added_file_paths [Array<String>]
|
158
|
+
# @param excluded_file_paths [Array<String>]
|
159
|
+
# @return [void]
|
160
|
+
def update_document_info(doc, added_file_paths, excluded_file_paths)
|
161
|
+
today = Time.now.strftime("%F")
|
165
162
|
|
166
|
-
|
167
|
-
|
168
|
-
entry["date"] = today
|
169
|
-
entry["sha"] = commit_sha(path)
|
170
|
-
end
|
163
|
+
doc["date"] = today
|
164
|
+
doc["sources"] ||= {}
|
171
165
|
|
172
|
-
|
166
|
+
added_file_paths.each do |path|
|
167
|
+
entry = (doc["sources"][path] ||= {})
|
168
|
+
entry["date"] = today
|
169
|
+
entry["sha"] = commit_sha(path)
|
173
170
|
end
|
171
|
+
|
172
|
+
excluded_file_paths.each { |x| doc["sources"].delete(x) }
|
174
173
|
end
|
175
174
|
end
|
data/lib/skap/cli.rb
CHANGED
@@ -13,22 +13,21 @@ require_relative "files/menu"
|
|
13
13
|
require_relative "files/sources"
|
14
14
|
require_relative "files/versions"
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
# Dispatcher for CLI commands.
|
17
|
+
module Skap::CLI
|
18
|
+
# @param argv [Array<String>]
|
19
|
+
# @return [void]
|
20
|
+
def self.start(argv = ARGV)
|
21
|
+
section, command, *rest = argv
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
23
|
+
case section
|
24
|
+
when "help", "--help", "-h", nil then Skap::CLI::Help.start
|
25
|
+
when "init" then Skap::CLI::Init.start(command, rest)
|
26
|
+
when "sources" then Skap::CLI::Sources.start(command, rest)
|
27
|
+
when "version", "--version", "-v" then Skap::CLI::Version.start
|
28
|
+
when "works" then Skap::CLI::Works.start(command, rest)
|
29
|
+
else
|
30
|
+
raise ArgumentError, "Unknown section: #{section}"
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
data/lib/skap/command.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
# Common class for CLI command.
|
4
|
+
module Skap::Command
|
5
|
+
CURRENT_DIR = Dir.pwd.freeze
|
6
6
|
|
7
|
-
|
7
|
+
private
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
# @return [void]
|
10
|
+
def assert_cwd
|
11
|
+
raise "Current dir isn't a repo for sources" if !File.exist?(Skap::Files::Sources.file_name)
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
# @param args [Array<String>]
|
15
|
+
# @return [void]
|
16
|
+
def assert_empty_options(args)
|
17
|
+
raise ArgumentError, "Unknown options: #{args.inspect}" if !args.empty?
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
20
|
+
# @param cmd [String]
|
21
|
+
# @param dir [String]
|
22
|
+
# @return [String]
|
23
|
+
def shell(cmd, dir: "")
|
24
|
+
dir = dir == "~" ? Dir.home : File.absolute_path(dir, CURRENT_DIR)
|
25
|
+
`cd #{dir} && #{cmd}`.strip
|
27
26
|
end
|
28
27
|
end
|
data/lib/skap/files/menu.rb
CHANGED
@@ -2,16 +2,13 @@
|
|
2
2
|
|
3
3
|
require "forwardable"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
extend Forwardable
|
5
|
+
# Class for file "menu.yaml" (this file is part of Skap).
|
6
|
+
class Skap::Files::Menu < Skap::YAMLFile
|
7
|
+
extend Forwardable
|
9
8
|
|
10
|
-
|
9
|
+
SKAP_DIR = File.expand_path("../../..", __dir__).freeze
|
11
10
|
|
12
|
-
|
11
|
+
self.file_name = File.join(SKAP_DIR, "menu.yaml")
|
13
12
|
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
13
|
+
def_delegators :file, :each
|
17
14
|
end
|
data/lib/skap/files/sources.rb
CHANGED
@@ -1,41 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
self.file_name = "sources.yaml"
|
3
|
+
# Class for file "sources.yaml" (this file describes sources in project repository).
|
4
|
+
class Skap::Files::Sources < Skap::YAMLFile
|
5
|
+
self.file_name = "sources.yaml"
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
# @param dir [String]
|
8
|
+
# @return [void]
|
9
|
+
def add_source(dir)
|
10
|
+
file[dir] = {"file-extensions" => [], "ignored" => [], "indexed" => []}
|
11
|
+
@file = file.sort_by(&:first).to_h
|
13
12
|
|
14
|
-
|
15
|
-
|
13
|
+
update_file
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
# @param dir [String]
|
17
|
+
# @return [void]
|
18
|
+
def delete_source(dir)
|
19
|
+
file.delete(dir)
|
20
|
+
update_file
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
# @param key [String]
|
24
|
+
# @param dirs [Array<String>]
|
25
|
+
# @return [Hash<String, Array<String>>]
|
26
|
+
def extract(key, dirs = [])
|
27
|
+
sources = dirs.empty? ? file : file.slice(*dirs)
|
28
|
+
sources
|
29
|
+
.transform_values { |v| v[key] }
|
30
|
+
.reject { |_, v| v.nil? || v.empty? }
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
33
|
+
# @param dirs [Array<String>]
|
34
|
+
# @return [Hash<String, Hash<String, Array<String>>>]
|
35
|
+
def select_directories!(dirs)
|
36
|
+
@file = file.slice(*dirs)
|
40
37
|
end
|
41
38
|
end
|
data/lib/skap/files/versions.rb
CHANGED
@@ -1,48 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
source_path if !sha.nil? && sha != source_data["sha"]
|
42
|
-
end
|
43
|
-
[doc_path, outdated_sources] if !outdated_sources.empty?
|
3
|
+
# Class for file "versions.yaml" (this file describes versions of works in project repository).
|
4
|
+
class Skap::Files::Versions < Skap::YAMLFile
|
5
|
+
self.file_name = "versions.yaml"
|
6
|
+
|
7
|
+
# @param document_path [String]
|
8
|
+
# @param document [Hash<String, Object>]
|
9
|
+
# @return [void]
|
10
|
+
def add_document(document_path, document)
|
11
|
+
file[document_path] = document
|
12
|
+
@file = file.sort_by(&:first).to_h
|
13
|
+
|
14
|
+
update_file
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Set<String>]
|
18
|
+
def covered_sources
|
19
|
+
result = Set.new
|
20
|
+
|
21
|
+
file.each_value { |value| result.merge(value["sources"].keys) }
|
22
|
+
|
23
|
+
result
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param document_path [String]
|
27
|
+
# @return [Hash<String, Object>]
|
28
|
+
def find_document(document_path)
|
29
|
+
file[document_path]
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Array<Array(String, Array<String>)>]
|
33
|
+
def outdated_documents
|
34
|
+
sources_sha = {}
|
35
|
+
|
36
|
+
file.filter_map do |doc_path, hash|
|
37
|
+
outdated_sources =
|
38
|
+
hash["sources"].filter_map do |source_path, source_data|
|
39
|
+
sha = (sources_sha[source_path] ||= yield(source_path))
|
40
|
+
source_path if !sha.nil? && sha != source_data["sha"]
|
44
41
|
end
|
45
|
-
|
42
|
+
[doc_path, outdated_sources] if !outdated_sources.empty?
|
46
43
|
end
|
47
44
|
end
|
48
45
|
end
|
data/lib/skap/string_utils.rb
CHANGED
@@ -1,49 +1,48 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
3
|
+
# Manipulations with strings.
|
4
|
+
module Skap::StringUtils
|
5
|
+
extend self
|
6
|
+
|
7
|
+
# @param paragraph [String]
|
8
|
+
# @param max_width [Integer]
|
9
|
+
# @return [Array<String>]
|
10
|
+
def break_by_words(paragraph, max_width)
|
11
|
+
words = paragraph.split
|
12
|
+
parts = [[]]
|
13
|
+
line_width = 0
|
14
|
+
|
15
|
+
while !words.empty?
|
16
|
+
word = words.shift
|
17
|
+
new_line_width = (line_width == 0 ? line_width : line_width + 1) + word.size
|
18
|
+
line_width = add_word(word, parts, new_line_width, max_width)
|
19
|
+
end
|
20
20
|
|
21
|
-
|
21
|
+
parts.pop if parts.last.empty?
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
parts.map { |line| line.join(" ") }
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# @param word [String]
|
29
|
+
# @param parts [Array<String>]
|
30
|
+
# @param new_line_width [Integer]
|
31
|
+
# @param max_width [Integer]
|
32
|
+
# @return [Integer] Current line width
|
33
|
+
def add_word(word, parts, new_line_width, max_width) # rubocop:disable Metrics/MethodLength
|
34
|
+
if new_line_width <= max_width
|
35
|
+
parts.last << word
|
25
36
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# @param parts [Array<String>]
|
30
|
-
# @param new_line_width [Integer]
|
31
|
-
# @param max_width [Integer]
|
32
|
-
# @return [Integer] Current line width
|
33
|
-
def add_word(word, parts, new_line_width, max_width) # rubocop:disable Metrics/MethodLength
|
34
|
-
if new_line_width <= max_width
|
35
|
-
parts.last << word
|
36
|
-
|
37
|
-
if new_line_width == max_width
|
38
|
-
parts << []
|
39
|
-
0
|
40
|
-
else
|
41
|
-
new_line_width
|
42
|
-
end
|
37
|
+
if new_line_width == max_width
|
38
|
+
parts << []
|
39
|
+
0
|
43
40
|
else
|
44
|
-
|
45
|
-
word.size
|
41
|
+
new_line_width
|
46
42
|
end
|
43
|
+
else
|
44
|
+
parts << [word]
|
45
|
+
word.size
|
47
46
|
end
|
48
47
|
end
|
49
48
|
end
|
data/lib/skap/version.rb
CHANGED
data/lib/skap/yaml_file.rb
CHANGED
@@ -1,29 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# Common class for reading & updating YAML files.
|
4
|
+
class Skap::YAMLFile
|
5
|
+
class << self
|
6
|
+
attr_accessor :file_name
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
private :file_name=
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def initialize
|
12
|
+
@file = load_file
|
13
|
+
end
|
14
14
|
|
15
|
-
|
15
|
+
private
|
16
16
|
|
17
|
-
|
17
|
+
attr_reader :file
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
# @return [Hash<String, Object>]
|
20
|
+
def load_file
|
21
|
+
Psych.load_file(self.class.file_name, symbolize_names: false) || {}
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
24
|
+
# @return [void]
|
25
|
+
def update_file
|
26
|
+
File.write(self.class.file_name, Psych.dump(file, line_width: 100))
|
28
27
|
end
|
29
28
|
end
|
data/lib/skap.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evgeniy Nochevnov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: '0'
|
128
128
|
requirements: []
|
129
|
-
rubygems_version: 3.5.
|
129
|
+
rubygems_version: 3.5.23
|
130
130
|
signing_key:
|
131
131
|
specification_version: 4
|
132
132
|
summary: ''
|