yorobot 0.2.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/Manifest.txt +0 -5
- data/Rakefile +5 -2
- data/lib/yorobot.rb +79 -16
- data/lib/yorobot/version.rb +3 -3
- metadata +46 -9
- data/lib/yorobot/base.rb +0 -124
- data/lib/yorobot/echo.rb +0 -13
- data/lib/yorobot/github/git.rb +0 -109
- data/lib/yorobot/github/github.rb +0 -30
- data/lib/yorobot/list.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 580be5dddb11eca11091ffde893fccf40b0913db
|
4
|
+
data.tar.gz: e43174dd09b69c60d800298cacde52cf65b159b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b915e306e9514d26f206d71d033dc00fc19c2eaf4062ce74b9521caf04228a8fe88a59b37db76da0b124609b460ba261671049696ec8771dc62eb29532d798c7
|
7
|
+
data.tar.gz: 5c0c1cbf3cbbd342f8b77f6f87580d0cf262c8d83b519d8dacfef0949bbd8597499fc9ee389c707e58355df81e5e1a89015ed388d6a0664a0d29b93e65af8878
|
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -18,8 +18,11 @@ Hoe.spec 'yorobot' do
|
|
18
18
|
self.history_file = 'CHANGELOG.md'
|
19
19
|
|
20
20
|
self.extra_deps = [
|
21
|
-
['
|
22
|
-
['
|
21
|
+
['flow-lite', '>= 1.0.1'],
|
22
|
+
['gitti', '>= 0.6.1'],
|
23
|
+
['hubba', '>= 1.0.0'],
|
24
|
+
['hubba-reports', '>= 1.0.1'],
|
25
|
+
['monos', '>= 1.0.2'],
|
23
26
|
]
|
24
27
|
|
25
28
|
self.licenses = ['Public Domain']
|
data/lib/yorobot.rb
CHANGED
@@ -1,34 +1,97 @@
|
|
1
|
+
require 'flow-lite'
|
2
|
+
|
3
|
+
|
1
4
|
####
|
2
|
-
# 3rd party gems / libs
|
5
|
+
# add more 3rd party gems / libs to flow "prologue / prelude"
|
3
6
|
#
|
4
7
|
# require 'computer' # add shell run/call etc. machinery
|
5
8
|
# add via gitti & hubba
|
6
9
|
require 'gitti'
|
7
10
|
require 'hubba'
|
11
|
+
require 'hubba/reports'
|
12
|
+
require 'mono'
|
8
13
|
|
9
14
|
|
10
15
|
# our own code
|
11
16
|
require 'yorobot/version' # note: let version always go first
|
12
|
-
require 'yorobot/base'
|
13
|
-
require 'yorobot/echo'
|
14
|
-
require 'yorobot/list'
|
15
17
|
|
16
|
-
require 'yorobot/github/git'
|
17
|
-
require 'yorobot/github/github'
|
18
18
|
|
19
19
|
|
20
|
+
#### add predefined steps
|
21
|
+
module Flow
|
22
|
+
class Base
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
=begin
|
25
|
+
# check ssh
|
26
|
+
if [ ! -d ~/.ssh ]; then mkdir ~/.ssh; fi
|
27
|
+
echo "$SSH_KEY" > ~/.ssh/id_rsa
|
28
|
+
chmod 600 ~/.ssh/id_rsa
|
29
|
+
echo "ssh directory - ~/.ssh:"
|
30
|
+
ls -la ~/.ssh
|
31
|
+
# ssh -vT git@github.com
|
32
|
+
|
33
|
+
# check git
|
34
|
+
git --version
|
35
|
+
git config --global user.name "Yo Robot"
|
36
|
+
git config --global user.email "gerald.bauer+yorobot@gmail.com"
|
37
|
+
git config -l --show-origin
|
38
|
+
=end
|
39
|
+
def step_setup
|
40
|
+
##############
|
41
|
+
## setup ssh
|
42
|
+
|
43
|
+
ssh_key = ENV['SSH_KEY']
|
44
|
+
|
45
|
+
if ssh_key.nil?
|
46
|
+
STDERR.puts "!! ERROR - required SSH_KEY env(ironment) variable missing"
|
47
|
+
exit 1
|
30
48
|
end
|
31
|
-
|
49
|
+
|
50
|
+
ssh_path = File.expand_path( '~/.ssh' )
|
51
|
+
|
52
|
+
if File.exist?( "#{ssh_path}/id_rsa" )
|
53
|
+
STDERR.puts "!! ERROR - ssh key >#{ssh_path}/id_rsa< already exists"
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
|
57
|
+
## make sure path exists
|
58
|
+
FileUtils.mkdir_p( ssh_path ) unless Dir.exist?( ssh_path )
|
59
|
+
puts "--> writing ssh key to >#{ssh_path}/id_rsa<..."
|
60
|
+
File.open( "#{ssh_path}/id_rsa", 'w:utf-8' ) do |f|
|
61
|
+
f.write( ssh_key )
|
62
|
+
end
|
63
|
+
## note: ssh key must be "private" only access by owner (otherwise) WILL NOT work
|
64
|
+
## res = File.chmod( 0600, "#{ssh_path}/id_rsa" )
|
65
|
+
## puts res ## returns number of files processed; should be 1 - assert - why? why not?
|
66
|
+
Computer::Shell.run( %Q{chmod 600 #{ssh_path}/id_rsa} )
|
67
|
+
|
68
|
+
Computer::Shell.run( %Q{ls -la #{ssh_path}} )
|
69
|
+
# ssh -vT git@github.com
|
70
|
+
|
71
|
+
|
72
|
+
#####
|
73
|
+
## setup git
|
74
|
+
## git --version
|
75
|
+
Git.version
|
76
|
+
|
77
|
+
user_name = ENV['YOROBOT_NAME'] || ENV['YO_NAME'] || 'Yo Robot'
|
78
|
+
user_email = ENV['YOROBOT_EMAIL'] || ENV['YO_EMAIL'] || 'gerald.bauer+yorobot@gmail.com'
|
79
|
+
|
80
|
+
Computer::Shell.run( %Q{git config --global user.name "#{user_name}"} )
|
81
|
+
Computer::Shell.run( %Q{git config --global user.email "#{user_email}"} )
|
82
|
+
|
83
|
+
Computer::Shell.run( %Q{git config -l --show-origin} )
|
84
|
+
end
|
85
|
+
|
86
|
+
end # class Base
|
87
|
+
end # module Flow
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
module Yorobot
|
94
|
+
Tool = ::Flow::Tool
|
32
95
|
end # module Yorobot
|
33
96
|
|
34
97
|
|
data/lib/yorobot/version.rb
CHANGED
@@ -4,9 +4,9 @@
|
|
4
4
|
|
5
5
|
|
6
6
|
module YorobotCore ## todo/check: rename GittiBase or GittiMeta or such - why? why not?
|
7
|
-
MAJOR =
|
8
|
-
MINOR =
|
9
|
-
PATCH =
|
7
|
+
MAJOR = 1 ## todo: namespace inside version or something - why? why not??
|
8
|
+
MINOR = 0
|
9
|
+
PATCH = 3
|
10
10
|
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
11
11
|
|
12
12
|
def self.version
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yorobot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: flow-lite
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.1
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: gitti
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - ">="
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
33
|
+
version: 0.6.1
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
40
|
+
version: 0.6.1
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: hubba
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,34 @@ dependencies:
|
|
38
52
|
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: 1.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hubba-reports
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: monos
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.2
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.2
|
41
83
|
- !ruby/object:Gem::Dependency
|
42
84
|
name: rdoc
|
43
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,11 +133,6 @@ files:
|
|
91
133
|
- bin/yo
|
92
134
|
- bin/yorobot
|
93
135
|
- lib/yorobot.rb
|
94
|
-
- lib/yorobot/base.rb
|
95
|
-
- lib/yorobot/echo.rb
|
96
|
-
- lib/yorobot/github/git.rb
|
97
|
-
- lib/yorobot/github/github.rb
|
98
|
-
- lib/yorobot/list.rb
|
99
136
|
- lib/yorobot/version.rb
|
100
137
|
homepage: https://github.com/rubycoco/git
|
101
138
|
licenses:
|
data/lib/yorobot/base.rb
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
module Yorobot
|
2
|
-
|
3
|
-
|
4
|
-
class Step
|
5
|
-
|
6
|
-
def self.option_defs
|
7
|
-
@option_defs ||= {}
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.option( key, *args )
|
11
|
-
option_defs[ key ] = args
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def options
|
17
|
-
@options ||= {}
|
18
|
-
end
|
19
|
-
|
20
|
-
def parse!( args )
|
21
|
-
### todo/check - cache option parser!!!! - why? why not?
|
22
|
-
OptionParser.new do |parser|
|
23
|
-
## add default banner - overwrite if needed/to customize
|
24
|
-
parser.banner = <<TXT
|
25
|
-
|
26
|
-
Usage: #{name} [OPTIONS] ARGUMENTS
|
27
|
-
|
28
|
-
TXT
|
29
|
-
|
30
|
-
self.class.option_defs.each do | key, on_args|
|
31
|
-
parser.on( *on_args ) do |value|
|
32
|
-
options[ key ] = value
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end.parse!( args )
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def self.run( args=[] )
|
41
|
-
step = new
|
42
|
-
|
43
|
-
puts "--> (#{step.name}) #{args.join('·')}"
|
44
|
-
|
45
|
-
## check for options
|
46
|
-
step.parse!( args )
|
47
|
-
|
48
|
-
puts " #{step.options.size} opt(s): #{step.options.pretty_inspect}"
|
49
|
-
puts " #{args.size} arg(s):"
|
50
|
-
args.each_with_index do |arg,i|
|
51
|
-
puts " #{[i]} >#{arg}<"
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
if args.size > 0
|
56
|
-
## todo/check: check/verify arity of run - why? why not?
|
57
|
-
step.call( *args ) ## use run - why? why not?
|
58
|
-
else
|
59
|
-
step. call
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
def self.step_name
|
65
|
-
## note: cut-off leading Yorobot:: for now in class name!!!
|
66
|
-
## note: always remove _ for now too!!!
|
67
|
-
## note: do NOT use @@name!!! - one instance variable per class needed!!
|
68
|
-
@name ||= self.name.downcase
|
69
|
-
.sub( /^yorobot::/, '' )
|
70
|
-
.gsub( /[_-]/, '' )
|
71
|
-
@name
|
72
|
-
end
|
73
|
-
|
74
|
-
def name() self.class.step_name; end
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
def self.inherited( klass )
|
81
|
-
# puts klass.class.name #=> Class
|
82
|
-
## auto-register steps for now - why? why not?
|
83
|
-
Yorobot.register( klass )
|
84
|
-
end
|
85
|
-
|
86
|
-
end # class Step
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
def self.steps ## todo/check: change to registry or such - why? why not?
|
91
|
-
@@register ||= {}
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.register( klass )
|
95
|
-
raise ArgumentError, "class MUST be a Yorobot::Step" unless klass.ancestors.include?( Step )
|
96
|
-
|
97
|
-
h = steps
|
98
|
-
h[ klass.step_name] = klass
|
99
|
-
h
|
100
|
-
end
|
101
|
-
|
102
|
-
|
103
|
-
def self.run( args=[] )
|
104
|
-
step_name = args.shift
|
105
|
-
|
106
|
-
## 1) downcase e.g. GithubStats
|
107
|
-
## 2) remove - to _ ## treat them the same e.g. github-stats => github_stats
|
108
|
-
step_name = step_name
|
109
|
-
.gsub( /[_-]/, '' )
|
110
|
-
.downcase
|
111
|
-
|
112
|
-
step = steps[ step_name ]
|
113
|
-
if step.nil?
|
114
|
-
puts "!! ERROR: no step definition found for >#{step_name}<; known steps include:"
|
115
|
-
List.run
|
116
|
-
exit 1
|
117
|
-
end
|
118
|
-
|
119
|
-
step.run( args )
|
120
|
-
end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end # module Yorobot
|
data/lib/yorobot/echo.rb
DELETED
data/lib/yorobot/github/git.rb
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
module Yorobot
|
2
|
-
|
3
|
-
|
4
|
-
class Setup < Step
|
5
|
-
|
6
|
-
=begin
|
7
|
-
# check ssh
|
8
|
-
if [ ! -d ~/.ssh ]; then mkdir ~/.ssh; fi
|
9
|
-
echo "$SSH_KEY" > ~/.ssh/id_rsa
|
10
|
-
chmod 600 ~/.ssh/id_rsa
|
11
|
-
echo "ssh directory - ~/.ssh:"
|
12
|
-
ls -la ~/.ssh
|
13
|
-
# ssh -vT git@github.com
|
14
|
-
|
15
|
-
# check git
|
16
|
-
git --version
|
17
|
-
git config --global user.name "Yo Robot"
|
18
|
-
git config --global user.email "gerald.bauer+yorobot@gmail.com"
|
19
|
-
git config -l --show-origin
|
20
|
-
=end
|
21
|
-
|
22
|
-
def call
|
23
|
-
##############
|
24
|
-
## setup ssh
|
25
|
-
|
26
|
-
ssh_key = ENV['SSH_KEY']
|
27
|
-
|
28
|
-
if ssh_key.nil?
|
29
|
-
STDERR.puts "!! ERROR - required SSH_KEY env(ironment) variable missing"
|
30
|
-
exit 1
|
31
|
-
end
|
32
|
-
|
33
|
-
ssh_path = File.expand_path( '~/.ssh' )
|
34
|
-
|
35
|
-
if File.exist?( "#{ssh_path}/id_rsa" )
|
36
|
-
STDERR.puts "!! ERROR - ssh key >#{ssh_path}/id_rsa< already exists"
|
37
|
-
exit 1
|
38
|
-
end
|
39
|
-
|
40
|
-
## make sure path exists
|
41
|
-
FileUtils.mkdir_p( ssh_path ) unless Dir.exist?( ssh_path )
|
42
|
-
puts "--> writing ssh key to >#{ssh_path}/id_rsa<..."
|
43
|
-
File.open( "#{ssh_path}/id_rsa", 'w:utf-8' ) do |f|
|
44
|
-
f.write( ssh_key )
|
45
|
-
end
|
46
|
-
## note: ssh key must be "private" only access by owner (otherwise) WILL NOT work
|
47
|
-
## res = File.chmod( 0600, "#{ssh_path}/id_rsa" )
|
48
|
-
## puts res ## returns number of files processed; should be 1 - assert - why? why not?
|
49
|
-
Computer::Shell.run( %Q{chmod 600 #{ssh_path}/id_rsa} )
|
50
|
-
|
51
|
-
Computer::Shell.run( %Q{ls -la #{ssh_path}} )
|
52
|
-
# ssh -vT git@github.com
|
53
|
-
|
54
|
-
|
55
|
-
#####
|
56
|
-
## setup git
|
57
|
-
## git --version
|
58
|
-
Git.version
|
59
|
-
|
60
|
-
user_name = ENV['YOROBOT_NAME'] || ENV['YO_NAME']
|
61
|
-
user_email = ENV['YOROBOT_EMAIL'] || ENV['YO_EMAIL']
|
62
|
-
|
63
|
-
Computer::Shell.run( %Q{git config --global user.name "#{user_name}"} )
|
64
|
-
Computer::Shell.run( %Q{git config --global user.email "#{user_email}"} )
|
65
|
-
|
66
|
-
Computer::Shell.run( %Q{git config -l --show-origin} )
|
67
|
-
end
|
68
|
-
end # class Setup
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
class Clone < Step ## change to SshClone(r) or such - why? why not?
|
73
|
-
option :depth, "--depth DEPTH", Integer, "shallow clone depth"
|
74
|
-
|
75
|
-
def call( *repos )
|
76
|
-
repos.each do |repo|
|
77
|
-
if options[:depth]
|
78
|
-
### shallow "fast clone" - support libraries
|
79
|
-
### use https:// instead of ssh - why? why not?
|
80
|
-
Git.clone( "git@github.com:#{repo}.git", depth: options[:depth] )
|
81
|
-
else
|
82
|
-
### "deep" standard/ regular clone
|
83
|
-
Git.clone( "git@github.com:#{repo}.git" )
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end # class Clone
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
class Push < Step ## change to SshPush(r) or such - why? why not?
|
92
|
-
|
93
|
-
def call( *paths ) ## e.g. "./cache.github" etc.
|
94
|
-
msg = "auto-update week #{Date.today.cweek}"
|
95
|
-
|
96
|
-
paths.each do |path|
|
97
|
-
GitProject.open( path ) do |proj|
|
98
|
-
if proj.changes?
|
99
|
-
proj.add( "." )
|
100
|
-
proj.commit( msg )
|
101
|
-
proj.push
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end # class Push
|
107
|
-
|
108
|
-
|
109
|
-
end # module Yorobot
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Yorobot
|
2
|
-
|
3
|
-
class Github < Step ## change to GithubStats or such - why? why not?
|
4
|
-
|
5
|
-
## todo/check: use --data-dir/--datadir - why? why not?
|
6
|
-
option :data_dir, "-d DIR", "--dir DIR",
|
7
|
-
"data dir (defaults to #{Hubba.config.data_dir})"
|
8
|
-
|
9
|
-
## todo/check: add switch --[no]-traffic - why? why not?
|
10
|
-
|
11
|
-
|
12
|
-
def call( username )
|
13
|
-
## username e.g. geraldb
|
14
|
-
|
15
|
-
if options[:data_dir] ## e.g. "./cache.github"
|
16
|
-
puts " setting data_dir to >#{options[:data_dir]}<"
|
17
|
-
Hubba.config.data_dir = options[:data_dir]
|
18
|
-
end
|
19
|
-
|
20
|
-
h = Hubba.reposet( username ) ## note: do NOT include yorobot for now
|
21
|
-
pp h
|
22
|
-
|
23
|
-
Hubba.update_stats( h )
|
24
|
-
Hubba.update_traffic( h )
|
25
|
-
puts "Done."
|
26
|
-
end
|
27
|
-
|
28
|
-
end # class Github
|
29
|
-
end # module Yorobot
|
30
|
-
|
data/lib/yorobot/list.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Yorobot
|
2
|
-
|
3
|
-
|
4
|
-
class List < Step
|
5
|
-
|
6
|
-
def call
|
7
|
-
## list all know steps
|
8
|
-
steps = Yorobot.steps
|
9
|
-
puts "#{steps.size} step(s):"
|
10
|
-
steps.each do |name, step|
|
11
|
-
puts " #{name} | #{step.class.name}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
end # module Yorobot
|
17
|
-
|
18
|
-
|
19
|
-
#####
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# -- add "shortcut why? why not?"
|
23
|
-
# step [:list, :ls] do |args|
|
24
|
-
# ....
|
25
|
-
# end
|