omegaup 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile +0 -0
- data/lib/omega/base.rb +0 -0
- data/lib/omega/cli/contest.rb +17 -0
- data/lib/omega/cli.rb +17 -2
- data/lib/omega/client.rb +116 -2
- data/lib/omega/contest.rb +24 -0
- data/lib/omega/contest_run.rb +1 -1
- data/lib/omega/scoreboard.rb +9 -1
- data/lib/omega/user.rb +5 -1
- data/lib/omega/version.rb +1 -1
- data/lib/omega.rb +0 -0
- data/omega.gemspec +5 -4
- metadata +19 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 767e4b440acdf0d4b4f07d2fa568b0c05e78a8e066e1280765d49c6d62b23c46
|
4
|
+
data.tar.gz: 4151f5ade0af99d594d81e7cb1dae1259532d0627cc1c02f0499e1db03c4cec3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2511e42ce423bb7530f9e696e2a8f436fe547a9526731e3fc119952d63a014c0ef151b2ed78087b033009ee3420fe5bfee6495fe0b35f33a92aff90d62ee1488
|
7
|
+
data.tar.gz: b0816baf5e9fb16c43a9dbdb2e00b8c1462fd0f77ae33ce843c9fc03d42f6491e75d492a4d3847591cd9cf225589a6b2b23601ce333ee90c23873814cce80e90
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
File without changes
|
data/lib/omega/base.rb
CHANGED
File without changes
|
data/lib/omega/cli/contest.rb
CHANGED
@@ -51,6 +51,23 @@ module Omega
|
|
51
51
|
puts "#{contest_name}: #{e.message}"
|
52
52
|
end
|
53
53
|
|
54
|
+
def add_problem(contest_name, problem_name)
|
55
|
+
contest = omega.contest(contest_name)
|
56
|
+
contest.add_problem(problem_name)
|
57
|
+
rescue StandardError => e
|
58
|
+
puts "Error adding #{problem_name}: #{e.message}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def copy_problems(contest_name, from)
|
62
|
+
contest = omega.contest(contest_name)
|
63
|
+
source = omega.contest(from)
|
64
|
+
source.problems.each do |problem|
|
65
|
+
contest.add_problem(problem[:alias])
|
66
|
+
rescue StandardError => e
|
67
|
+
puts "Error adding #{problem[:alias]}: #{e.message}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
54
71
|
def download_sources(contest_name, path)
|
55
72
|
Dir.mkdir(path) unless File.directory?(path)
|
56
73
|
contest = omega.contest(contest_name)
|
data/lib/omega/cli.rb
CHANGED
@@ -24,6 +24,7 @@ OmegaUp CLI. Developed by OMIJal https://github.com/omijal/omegaup-cli.
|
|
24
24
|
Tool for interacting with omegaup from CLI and available throug ruby gems.
|
25
25
|
Commands:
|
26
26
|
- register-users Add a user or a bunch of users to the a contest.
|
27
|
+
- copy-problems Adds prob from another contest
|
27
28
|
- user Generates a dump of the user data in yml format.
|
28
29
|
- scoreboard Gets contest scoreboard with users and score.
|
29
30
|
- clarifications Gets contest clarifications.
|
@@ -51,6 +52,16 @@ OMEGAUP_PASS *Required* Your OmegaUp Password
|
|
51
52
|
@cmd = ARGV.shift
|
52
53
|
|
53
54
|
@cmd_opts = case @cmd
|
55
|
+
when 'copy-problems'
|
56
|
+
Optimist.options do
|
57
|
+
opt :contest, 'Contest ShortName or identifier', type: :string
|
58
|
+
opt :from, 'Another constest that allows to clone users from another contest', type: :string
|
59
|
+
end
|
60
|
+
when 'add-problem'
|
61
|
+
Optimist.options do
|
62
|
+
opt :contest, 'Contest ShortName or identifier', type: :string
|
63
|
+
opt :problem, 'Problem name', type: :string
|
64
|
+
end
|
54
65
|
when 'register-users'
|
55
66
|
Optimist.options do
|
56
67
|
opt :contest, 'Contest ShortName or identifier', type: :string
|
@@ -95,8 +106,8 @@ OMEGAUP_PASS *Required* Your OmegaUp Password
|
|
95
106
|
config = {
|
96
107
|
'omega' => {
|
97
108
|
'endpoint' => ENV['OMEGAUP_URL'] || 'https://omegaup.com',
|
98
|
-
'user' => ENV
|
99
|
-
'pass' => ENV
|
109
|
+
'user' => ENV.fetch('OMEGAUP_USER', nil),
|
110
|
+
'pass' => ENV.fetch('OMEGAUP_PASS', nil)
|
100
111
|
}
|
101
112
|
}
|
102
113
|
|
@@ -119,6 +130,10 @@ OMEGAUP_PASS *Required* Your OmegaUp Password
|
|
119
130
|
clarifications(@cmd_opts[:contest], @cmd_opts[:open])
|
120
131
|
when 'sources'
|
121
132
|
download_sources(@cmd_opts[:contest], @cmd_opts[:path])
|
133
|
+
when 'copy-problems'
|
134
|
+
copy_problems(@cmd_opts[:contest], @cmd_opts[:from])
|
135
|
+
when 'add-problem'
|
136
|
+
add_problem(@cmd_opts[:contest], @cmd_opts[:problem])
|
122
137
|
end
|
123
138
|
end
|
124
139
|
end
|
data/lib/omega/client.rb
CHANGED
@@ -4,10 +4,16 @@ require_relative 'contest'
|
|
4
4
|
require_relative 'scoreboard'
|
5
5
|
require_relative 'user'
|
6
6
|
require_relative 'contest_run'
|
7
|
+
require 'json'
|
8
|
+
require 'nokogiri'
|
7
9
|
|
8
10
|
require 'httparty'
|
9
11
|
|
10
12
|
module Omega
|
13
|
+
KAREL_LANGS = 'kp,kj'
|
14
|
+
OMI_LANGS = 'c11-gcc,c11-clang,cpp11-gcc,cpp11-clang,cpp17-gcc,cpp17-clang,cpp20-gcc,cpp20-clang'
|
15
|
+
ALL_LANGS = 'kp,kj,c11-gcc,c11-clang,cpp11-gcc,cpp11-clang,cpp17-gcc,cpp17-clang,cpp20-gcc,cpp20-clang,java,kt,py2,py3,rb,cs,pas,cat,hs,lua,go,rs,js'
|
16
|
+
|
11
17
|
class OmegaError < StandardError
|
12
18
|
attr_reader :data
|
13
19
|
|
@@ -18,6 +24,14 @@ module Omega
|
|
18
24
|
def message
|
19
25
|
"#{@data[:errorname]}::#{@data[:errorcode]} >> #{@data[:error]}"
|
20
26
|
end
|
27
|
+
|
28
|
+
def errorname
|
29
|
+
@data[:errorname]
|
30
|
+
end
|
31
|
+
|
32
|
+
def errorcode
|
33
|
+
@data[:errorcode]
|
34
|
+
end
|
21
35
|
end
|
22
36
|
|
23
37
|
class Client
|
@@ -30,7 +44,7 @@ module Omega
|
|
30
44
|
def perform_request(method, endpoint, data, retried = false)
|
31
45
|
url = "#{@config['endpoint']}#{endpoint}"
|
32
46
|
response = self.class.send(method, url, body: data)
|
33
|
-
body = JSON.parse(response.body, symbolize_names: true)
|
47
|
+
body = ::JSON.parse(response.body, symbolize_names: true)
|
34
48
|
|
35
49
|
if body[:errorcode] == 401 && !retried
|
36
50
|
login
|
@@ -67,6 +81,58 @@ module Omega
|
|
67
81
|
retry
|
68
82
|
end
|
69
83
|
|
84
|
+
def problem_details(problem_alias)
|
85
|
+
post('/api/problem/details', { problem_alias: })
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_group(name, description: nil, alias: nil)
|
89
|
+
post('/api/group/create', name:, alias:, description:)
|
90
|
+
end
|
91
|
+
|
92
|
+
def create_contest(name:, short_name:, description:, start_time:, finish_time:,
|
93
|
+
public: false, penalty_calc_policy: 'sum', show_penalty: true,
|
94
|
+
points_decay_factor: '0', submissions_gap: '60', languages: ALL_LANGS, feedback: 'none',
|
95
|
+
penalty: '0', scoreboard: '100', penalty_type: 'none',
|
96
|
+
default_show_all_contestants_in_scoreboard: false,
|
97
|
+
show_scoreboard_after: true,
|
98
|
+
score_mode: 'partial',
|
99
|
+
needs_basic_information: false,
|
100
|
+
requests_user_information: 'no',
|
101
|
+
contest_for_teams: false)
|
102
|
+
post('/api/contest/create/', {
|
103
|
+
admin: true,
|
104
|
+
admission_mode: (public ? 'public' : 'private'),
|
105
|
+
alias: short_name,
|
106
|
+
archived: false,
|
107
|
+
opened: false,
|
108
|
+
penalty_calc_policy:,
|
109
|
+
show_penalty:,
|
110
|
+
title: name,
|
111
|
+
description:,
|
112
|
+
has_submissions: false,
|
113
|
+
start_time: start_time.to_time.to_i,
|
114
|
+
finish_time: finish_time.to_time.to_i,
|
115
|
+
points_decay_factor:,
|
116
|
+
submissions_gap:,
|
117
|
+
languages:,
|
118
|
+
feedback:,
|
119
|
+
penalty:,
|
120
|
+
scoreboard:,
|
121
|
+
penalty_type:,
|
122
|
+
default_show_all_contestants_in_scoreboard:,
|
123
|
+
show_scoreboard_after:,
|
124
|
+
score_mode:,
|
125
|
+
needs_basic_information:,
|
126
|
+
requests_user_information:,
|
127
|
+
contest_for_teams:
|
128
|
+
})
|
129
|
+
contest(short_name)
|
130
|
+
rescue OmegaError => e
|
131
|
+
raise e unless e.errorname == 'aliasInUse'
|
132
|
+
|
133
|
+
contest(short_name)
|
134
|
+
end
|
135
|
+
|
70
136
|
def scoreboard(name)
|
71
137
|
data = post('/api/contest/scoreboard/', { contest_alias: name })
|
72
138
|
Scoreboard.new(self, data)
|
@@ -86,6 +152,12 @@ module Omega
|
|
86
152
|
User.new(self, data)
|
87
153
|
end
|
88
154
|
|
155
|
+
def add_admin_group(contest, group)
|
156
|
+
post('/api/contest/addGroupAdmin', { contest_alias: contest, group: })
|
157
|
+
rescue OmegaError
|
158
|
+
# Omega seems to have a bug
|
159
|
+
end
|
160
|
+
|
89
161
|
def add_user_to_contest(user, contest)
|
90
162
|
post('/api/contest/addUser', { contest_alias: contest, usernameOrEmail: user })
|
91
163
|
end
|
@@ -99,8 +171,50 @@ module Omega
|
|
99
171
|
end
|
100
172
|
|
101
173
|
def contest_runs(contest, offset, page_size)
|
102
|
-
data = post('/api/contest/runs/', { contest_alias: contest, offset
|
174
|
+
data = post('/api/contest/runs/', { contest_alias: contest, offset:, rowcount: page_size })
|
103
175
|
data[:runs].map { |run| ContestRun.new(self, run) }
|
104
176
|
end
|
177
|
+
|
178
|
+
def add_problem_to_contest(contest, problem, points = 100)
|
179
|
+
post('/api/contest/addProblem', contest_alias: contest, problem_alias: problem, points:)
|
180
|
+
end
|
181
|
+
|
182
|
+
def add_user_to_group(group_name, username)
|
183
|
+
post('/api/group/addUser', group_alias: group_name, usernameOrEmail: username)
|
184
|
+
rescue OmegaError => e
|
185
|
+
raise if e.errorname != 'identityInGroup'
|
186
|
+
end
|
187
|
+
|
188
|
+
def get_payload_from_response_by_id(response_body, id)
|
189
|
+
page = Nokogiri::HTML(response_body)
|
190
|
+
script = page.at_css("script##{id}")
|
191
|
+
unless script
|
192
|
+
raise OmegaError.new(errorname: 'ScrapingError', errorcode: 404,
|
193
|
+
error: "Script with id #{id} not found")
|
194
|
+
end
|
195
|
+
|
196
|
+
script_content = script.content
|
197
|
+
# Extrayendo el contenido JSON del script
|
198
|
+
begin
|
199
|
+
::JSON.parse(script_content, symbolize_names: true)
|
200
|
+
rescue JSON::ParserError
|
201
|
+
raise OmegaError.new(errorname: 'ScrapingError', errorcode: 500, error: 'Unable to parse JSON data')
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def scrap_get(endpoint, id = 'payload')
|
206
|
+
url = "#{@config['endpoint']}#{endpoint}"
|
207
|
+
response = self.class.get(url)
|
208
|
+
unless response.success?
|
209
|
+
raise OmegaError.new(errorname: 'HttpError', errorcode: response.code,
|
210
|
+
error: response.message)
|
211
|
+
end
|
212
|
+
|
213
|
+
body = get_payload_from_response_by_id(response.body, id)
|
214
|
+
|
215
|
+
raise OmegaError, body if body[:error]
|
216
|
+
|
217
|
+
body
|
218
|
+
end
|
105
219
|
end
|
106
220
|
end
|
data/lib/omega/contest.rb
CHANGED
@@ -9,6 +9,10 @@ module Omega
|
|
9
9
|
@client.scoreboard(data[:alias])
|
10
10
|
end
|
11
11
|
|
12
|
+
def problems
|
13
|
+
@data[:problems]
|
14
|
+
end
|
15
|
+
|
12
16
|
def runs(offset = 0, page_size = 100)
|
13
17
|
@client.contest_runs(data[:alias], offset, page_size)
|
14
18
|
end
|
@@ -27,6 +31,14 @@ module Omega
|
|
27
31
|
sources
|
28
32
|
end
|
29
33
|
|
34
|
+
def full_details
|
35
|
+
@full_details ||= @client.scrap_get("/contest/#{data[:alias]}/edit/")
|
36
|
+
end
|
37
|
+
|
38
|
+
def group_admin?(group_name)
|
39
|
+
full_details[:group_admins].any? { |group| group[:alias].casecmp(group_name).zero? }
|
40
|
+
end
|
41
|
+
|
30
42
|
def add_user(user)
|
31
43
|
if user.is_a?(String)
|
32
44
|
@client.add_user_to_contest(user, data[:alias])
|
@@ -43,6 +55,18 @@ module Omega
|
|
43
55
|
scoreboard.users
|
44
56
|
end
|
45
57
|
|
58
|
+
def alias
|
59
|
+
@data[:alias].downcase
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_problem(name)
|
63
|
+
@client.add_problem_to_contest(data[:alias], name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_admin_group(group)
|
67
|
+
@client.add_admin_group(data[:alias], group)
|
68
|
+
end
|
69
|
+
|
46
70
|
def observe(score_notifier, clar_noritifer)
|
47
71
|
last = current = scoreboard
|
48
72
|
sleep(5)
|
data/lib/omega/contest_run.rb
CHANGED
data/lib/omega/scoreboard.rb
CHANGED
@@ -10,7 +10,7 @@ module Omega
|
|
10
10
|
def initialize(client, entry)
|
11
11
|
@username = entry[:username]
|
12
12
|
@problems = entry[:problems] || []
|
13
|
-
super
|
13
|
+
super
|
14
14
|
end
|
15
15
|
|
16
16
|
def merge(score)
|
@@ -37,6 +37,10 @@ module Omega
|
|
37
37
|
end
|
38
38
|
nil
|
39
39
|
end
|
40
|
+
|
41
|
+
def to_h
|
42
|
+
@data[:problems]
|
43
|
+
end
|
40
44
|
end
|
41
45
|
|
42
46
|
class Scoreboard < Base
|
@@ -49,6 +53,10 @@ module Omega
|
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
56
|
+
def to_h
|
57
|
+
@data[:ranking].map { |username, entry| { username:, score: entry.to_h } }
|
58
|
+
end
|
59
|
+
|
52
60
|
def merge(board)
|
53
61
|
result = clone
|
54
62
|
board.data[:ranking].each do |user, score|
|
data/lib/omega/user.rb
CHANGED
@@ -7,7 +7,7 @@ module Omega
|
|
7
7
|
def full_data
|
8
8
|
{
|
9
9
|
data: @data,
|
10
|
-
problems_solved
|
10
|
+
problems_solved:,
|
11
11
|
resume: report
|
12
12
|
}
|
13
13
|
end
|
@@ -16,6 +16,10 @@ module Omega
|
|
16
16
|
@client.problems_solved(data[:username])[:problems]
|
17
17
|
end
|
18
18
|
|
19
|
+
def username
|
20
|
+
@data[:username]
|
21
|
+
end
|
22
|
+
|
19
23
|
def report
|
20
24
|
data = { score: 0, count: 0 }
|
21
25
|
problems_solved.each do |p|
|
data/lib/omega/version.rb
CHANGED
data/lib/omega.rb
CHANGED
File without changes
|
data/omega.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.name = 'omegaup'
|
9
9
|
spec.version = Omega::VERSION
|
10
10
|
spec.authors = ['Gilberto Vargas']
|
11
|
-
spec.email = ['
|
11
|
+
spec.email = ['tachomexgems@gmail.com']
|
12
12
|
|
13
13
|
spec.summary = 'File created for encrypting files using ssh keys'
|
14
14
|
spec.description = 'Allows to encrypt files using ssh keys'
|
@@ -25,10 +25,11 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency 'amazing_print'
|
26
26
|
spec.add_development_dependency 'httparty'
|
27
27
|
spec.add_development_dependency 'minitest', '~> 5'
|
28
|
+
spec.add_development_dependency 'mocha'
|
28
29
|
spec.add_development_dependency 'optimist'
|
29
30
|
spec.add_development_dependency 'rack-minitest'
|
30
|
-
spec.add_development_dependency 'webmock'
|
31
|
-
spec.add_development_dependency 'mocha'
|
32
|
-
spec.add_development_dependency 'simplecov'
|
33
31
|
spec.add_development_dependency 'rake', '~> 10.0'
|
32
|
+
spec.add_development_dependency 'simplecov'
|
33
|
+
spec.add_development_dependency 'webmock'
|
34
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
34
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omegaup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gilberto Vargas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: amazing_print
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: mocha
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: optimist
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rack-minitest
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,19 +95,19 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
103
|
+
version: '10.0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
110
|
+
version: '10.0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: simplecov
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,22 +123,22 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: webmock
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
138
|
+
version: '0'
|
139
139
|
description: Allows to encrypt files using ssh keys
|
140
140
|
email:
|
141
|
-
-
|
141
|
+
- tachomexgems@gmail.com
|
142
142
|
executables:
|
143
143
|
- omega
|
144
144
|
extensions: []
|
@@ -161,7 +161,8 @@ files:
|
|
161
161
|
homepage: https://github.com/omijal/omegaup-cli
|
162
162
|
licenses:
|
163
163
|
- MIT
|
164
|
-
metadata:
|
164
|
+
metadata:
|
165
|
+
rubygems_mfa_required: 'true'
|
165
166
|
post_install_message:
|
166
167
|
rdoc_options: []
|
167
168
|
require_paths:
|
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
178
|
- !ruby/object:Gem::Version
|
178
179
|
version: '0'
|
179
180
|
requirements: []
|
180
|
-
rubygems_version: 3.
|
181
|
+
rubygems_version: 3.5.14
|
181
182
|
signing_key:
|
182
183
|
specification_version: 4
|
183
184
|
summary: File created for encrypting files using ssh keys
|