git-contest 0.2.4 → 0.2.5
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 +8 -8
- data/.travis.yml +21 -3
- data/README.md +5 -0
- data/Rakefile +8 -0
- data/appveyor.yml +21 -0
- data/bin/git-contest +4 -33
- data/bin/git-contest-config +4 -241
- data/bin/git-contest-finish +4 -151
- data/bin/git-contest-init +4 -65
- data/bin/git-contest-list +4 -64
- data/bin/git-contest-rebase +4 -64
- data/bin/git-contest-start +4 -57
- data/bin/git-contest-submit +4 -183
- data/git-contest.gemspec +2 -1
- data/lib/contest/driver/base.rb +7 -4
- data/lib/git/contest/command_line.rb +10 -0
- data/lib/git/contest/command_line/command.rb +117 -0
- data/lib/git/contest/command_line/main_command.rb +56 -0
- data/lib/git/contest/command_line/sub_commands.rb +35 -0
- data/lib/git/contest/command_line/sub_commands/config_command.rb +258 -0
- data/lib/git/contest/command_line/sub_commands/finish_command.rb +161 -0
- data/lib/git/contest/command_line/sub_commands/init_command.rb +79 -0
- data/lib/git/contest/command_line/sub_commands/list_command.rb +89 -0
- data/lib/git/contest/command_line/sub_commands/rebase_command.rb +87 -0
- data/lib/git/contest/command_line/sub_commands/start_command.rb +77 -0
- data/lib/git/contest/command_line/sub_commands/submit_command.rb +220 -0
- data/lib/git/contest/common.rb +6 -6
- data/lib/git/contest/git.rb +160 -156
- data/lib/git/contest/version.rb +1 -1
- data/spec/command/t004_git_contest_submit_spec.rb +254 -0
- data/spec/command/t005_git_contest_branching_spec.rb +90 -0
- data/spec/command/t007_git_contest_start_spec.rb +95 -0
- data/spec/command/t008_git_contest_finish_spec.rb +171 -0
- data/spec/command/t009_git_contest_init_spec.rb +85 -0
- data/spec/command/t012_git_contest_list_spec.rb +123 -0
- data/spec/command/t013_git_contest_config_spec.rb +186 -0
- data/spec/{lib/contest/driver → contest_driver}/t001_aizu_online_judge_spec.rb +1 -1
- data/spec/{lib/contest/driver → contest_driver}/t002_codeforces_spec.rb +1 -1
- data/spec/{lib/contest/driver → contest_driver}/t003_uva_online_judge_spec.rb +1 -1
- data/spec/{lib/contest/driver → contest_driver}/t010_kattis_spec.rb +1 -1
- data/spec/{lib/contest/driver → contest_driver}/t011_utils_spec.rb +0 -0
- data/spec/spec_helper.rb +18 -12
- data/spec/t006_config_spec.rb +37 -31
- metadata +57 -33
- data/spec/bin/t004_git_contest_submit_spec.rb +0 -223
- data/spec/bin/t005_git_contest_branching_spec.rb +0 -70
- data/spec/bin/t007_git_contest_start_spec.rb +0 -88
- data/spec/bin/t008_git_contest_finish_spec.rb +0 -162
- data/spec/bin/t009_git_contest_init_spec.rb +0 -55
- data/spec/bin/t012_git_contest_list_spec.rb +0 -99
- data/spec/bin/t013_git_contest_config_spec.rb +0 -149
- data/spec/spec_list.txt +0 -1
data/git-contest.gemspec
CHANGED
@@ -28,10 +28,11 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_dependency "highline"
|
29
29
|
spec.add_dependency "activesupport"
|
30
30
|
|
31
|
-
spec.add_development_dependency "bundler"
|
31
|
+
spec.add_development_dependency "bundler"
|
32
32
|
spec.add_development_dependency "rake"
|
33
33
|
spec.add_development_dependency "watchr"
|
34
34
|
spec.add_development_dependency "rspec"
|
35
35
|
spec.add_development_dependency "webmock"
|
36
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
36
37
|
end
|
37
38
|
|
data/lib/contest/driver/base.rb
CHANGED
@@ -15,9 +15,12 @@ module Contest
|
|
15
15
|
DEFAULT_COMMIT_MESSAGE ="${site} ${problem-id}: ${status}"
|
16
16
|
|
17
17
|
class DriverBase < DriverEvent
|
18
|
-
attr_accessor :config
|
18
|
+
attr_accessor :config
|
19
|
+
attr_accessor :options
|
20
|
+
attr_reader :args
|
19
21
|
|
20
|
-
def initialize
|
22
|
+
def initialize(new_args = [])
|
23
|
+
@args = new_args.clone
|
21
24
|
# submit options
|
22
25
|
@options ||= {}
|
23
26
|
# site config
|
@@ -25,7 +28,7 @@ module Contest
|
|
25
28
|
@config["file"] ||= {}
|
26
29
|
@config["submit_rules"] ||= {}
|
27
30
|
# call DriverEvent#initialize
|
28
|
-
super
|
31
|
+
super()
|
29
32
|
initialize_ext
|
30
33
|
end
|
31
34
|
|
@@ -93,7 +96,7 @@ module Contest
|
|
93
96
|
:required => false,
|
94
97
|
)
|
95
98
|
end
|
96
|
-
Trollop::options
|
99
|
+
Trollop::options args, @blocks do |blocks|
|
97
100
|
version "git-contest driver"
|
98
101
|
# set driver options
|
99
102
|
blocks.each do |b|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#
|
2
|
+
# command_line.rb
|
3
|
+
#
|
4
|
+
# Copyright (c) 2014 Hiroyuki Sano <sh19910711 at gmail.com>
|
5
|
+
# Licensed under the MIT-License.
|
6
|
+
#
|
7
|
+
|
8
|
+
require_relative "command_line/command"
|
9
|
+
require_relative "command_line/sub_commands"
|
10
|
+
require_relative "command_line/main_command"
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#
|
2
|
+
# command.rb
|
3
|
+
#
|
4
|
+
# Copyright (c) 2014 Hiroyuki Sano <sh19910711 at gmail.com>
|
5
|
+
# Licensed under the MIT-License.
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# class SomeCommand < Command; end
|
11
|
+
# cli = SomeCommand.new [arg1, arg2, ...]
|
12
|
+
# cli.init
|
13
|
+
# cli.run
|
14
|
+
#
|
15
|
+
|
16
|
+
module CommandLine
|
17
|
+
|
18
|
+
require "optparse"
|
19
|
+
require "highline"
|
20
|
+
|
21
|
+
class Command
|
22
|
+
|
23
|
+
attr_reader :input_stream
|
24
|
+
attr_reader :terminal
|
25
|
+
attr_reader :args
|
26
|
+
attr_reader :tokens
|
27
|
+
attr_reader :options
|
28
|
+
attr_reader :opt_parser
|
29
|
+
|
30
|
+
def initialize(new_args, new_input_stream = STDIN)
|
31
|
+
@input_stream = new_input_stream
|
32
|
+
@terminal = ::HighLine.new(new_input_stream)
|
33
|
+
init_global # TODO: remove
|
34
|
+
init_home # TODO:remove
|
35
|
+
@args = new_args.clone
|
36
|
+
@options = {}
|
37
|
+
@tokens = [] # init after parse options
|
38
|
+
@opt_parser = OptionParser.new do |opt|
|
39
|
+
opt.version = Git::Contest::VERSION
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def define_options
|
44
|
+
raise "not implement"
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_default_options
|
48
|
+
raise "not implement"
|
49
|
+
end
|
50
|
+
|
51
|
+
def init
|
52
|
+
define_options
|
53
|
+
parse_line_options
|
54
|
+
@tokens = args
|
55
|
+
set_default_options
|
56
|
+
end
|
57
|
+
|
58
|
+
def run
|
59
|
+
raise "not implement"
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def parse_line_options
|
65
|
+
return if args.empty?
|
66
|
+
last_ind = last_line_option_index
|
67
|
+
if last_ind.nil?
|
68
|
+
parsed = args.clone
|
69
|
+
else
|
70
|
+
parsed = args[0 .. last_ind]
|
71
|
+
end
|
72
|
+
if last_ind.nil?
|
73
|
+
@args = opt_parser.parse(parsed)
|
74
|
+
else
|
75
|
+
@args = opt_parser.parse(parsed).concat(args[last_ind + 1..-1])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def last_line_option_index
|
80
|
+
args.index do |arg|
|
81
|
+
is_not_line_option?(arg)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# hello -> HelloCommand
|
86
|
+
def to_command_class_sym(s)
|
87
|
+
"#{s.capitalize}Command".to_sym
|
88
|
+
end
|
89
|
+
|
90
|
+
def is_line_option?(s)
|
91
|
+
return true if /^-[a-zA-Z0-9]$/ === s
|
92
|
+
return true if /^--/ === s
|
93
|
+
return false
|
94
|
+
end
|
95
|
+
|
96
|
+
def is_not_line_option?(s)
|
97
|
+
is_line_option?(s) === false
|
98
|
+
end
|
99
|
+
|
100
|
+
def has_subcommand?
|
101
|
+
return false if args.empty?
|
102
|
+
return false if args[0].start_with?("-")
|
103
|
+
return true
|
104
|
+
end
|
105
|
+
|
106
|
+
# [--opt1, --opt2, token1, token2] => token1
|
107
|
+
def next_token
|
108
|
+
@tokens.shift
|
109
|
+
end
|
110
|
+
|
111
|
+
def has_next_token?
|
112
|
+
not @tokens.empty?
|
113
|
+
end
|
114
|
+
|
115
|
+
end # Command
|
116
|
+
|
117
|
+
end # CommandLine
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module CommandLine
|
2
|
+
|
3
|
+
class MainCommand < Command
|
4
|
+
|
5
|
+
attr_reader :sub_commands
|
6
|
+
|
7
|
+
def initialize(new_args, new_input_stream = STDIN)
|
8
|
+
super
|
9
|
+
@sub_commands = SubCommands.all.freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def define_options
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_default_options
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
if has_subcommand?
|
20
|
+
command_name = args.shift
|
21
|
+
call_subcommand command_name
|
22
|
+
else
|
23
|
+
MainCommand.usage
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def call_subcommand(command_name)
|
30
|
+
sub_command = to_command_class_sym(command_name)
|
31
|
+
if sub_commands.include?(sub_command)
|
32
|
+
cli = SubCommands.const_get(sub_command).new(args, input_stream)
|
33
|
+
cli.init
|
34
|
+
cli.run
|
35
|
+
else
|
36
|
+
SubCommands.usage
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.usage
|
41
|
+
puts "usage: git contest <subcommand>"
|
42
|
+
puts ""
|
43
|
+
puts "Available subcommands are:"
|
44
|
+
puts " %-12s Initialize a new git repo." % ["init"]
|
45
|
+
puts " %-12s Start a new feature branch." % ["start"]
|
46
|
+
puts " %-12s Finish a feature branch." % ["finish"]
|
47
|
+
puts " %-12s Submit a solution." % ["submit"]
|
48
|
+
puts " %-12s Show information (sites, drivers)." % ["list"]
|
49
|
+
puts " %-12s Get/Set a config value." % ["config"]
|
50
|
+
puts ""
|
51
|
+
puts "Try 'git contest <subcommand> help' for details."
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "sub_commands/config_command"
|
2
|
+
require_relative "sub_commands/submit_command"
|
3
|
+
require_relative "sub_commands/init_command"
|
4
|
+
require_relative "sub_commands/start_command"
|
5
|
+
require_relative "sub_commands/finish_command"
|
6
|
+
require_relative "sub_commands/rebase_command"
|
7
|
+
require_relative "sub_commands/list_command"
|
8
|
+
|
9
|
+
module CommandLine
|
10
|
+
|
11
|
+
module SubCommands
|
12
|
+
|
13
|
+
def self.all
|
14
|
+
SubCommands.constants.select do |name|
|
15
|
+
/.+Command$/ === name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.usage
|
20
|
+
puts "usage: git contest <subcommand>"
|
21
|
+
puts ""
|
22
|
+
puts "Available subcommands are:"
|
23
|
+
puts " %-12s Initialize a new git repo." % ["init"]
|
24
|
+
puts " %-12s Start a new feature branch." % ["start"]
|
25
|
+
puts " %-12s Finish a feature branch." % ["finish"]
|
26
|
+
puts " %-12s Submit a solution." % ["submit"]
|
27
|
+
puts " %-12s Show information (sites, drivers)." % ["list"]
|
28
|
+
puts " %-12s Get/Set a config value." % ["config"]
|
29
|
+
puts ""
|
30
|
+
puts "Try 'git contest <subcommand> help' for details."
|
31
|
+
end
|
32
|
+
|
33
|
+
end # SubCommands
|
34
|
+
|
35
|
+
end # CommandLine
|
@@ -0,0 +1,258 @@
|
|
1
|
+
# https://github.com/sh19910711/git-contest
|
2
|
+
#
|
3
|
+
# Copyright (c) 2014 Hiroyuki Sano <sh19910711 at gmail.com>
|
4
|
+
# Licensed under the MIT-License.
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'git/contest/common'
|
8
|
+
require 'active_support/core_ext/hash'
|
9
|
+
|
10
|
+
module CommandLine
|
11
|
+
|
12
|
+
module SubCommands
|
13
|
+
|
14
|
+
class ConfigCommand < Command
|
15
|
+
|
16
|
+
def initialize(new_args, new_input_stream = STDIN)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def define_options
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_default_options
|
24
|
+
end
|
25
|
+
|
26
|
+
def run(input = "")
|
27
|
+
type = next_token
|
28
|
+
case type
|
29
|
+
|
30
|
+
when "site"
|
31
|
+
run_site
|
32
|
+
when "get"
|
33
|
+
run_get
|
34
|
+
when "set"
|
35
|
+
run_set
|
36
|
+
else
|
37
|
+
usage
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def update_config!(config, keys, value)
|
45
|
+
# update yaml value
|
46
|
+
new_config = {}
|
47
|
+
cur = new_config
|
48
|
+
while ! keys.empty?
|
49
|
+
key = keys.shift
|
50
|
+
if keys.empty?
|
51
|
+
cur[key] = value
|
52
|
+
else
|
53
|
+
cur[key] = {}
|
54
|
+
cur = cur[key]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
config.deep_merge! new_config
|
58
|
+
File.open($git_contest_config, 'w') {|f| f.write config.to_yaml }
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_set
|
62
|
+
if tokens.length == 1
|
63
|
+
# read values
|
64
|
+
keys = next_token.split('.')
|
65
|
+
puts "input value"
|
66
|
+
value = input_stream.gets.strip
|
67
|
+
|
68
|
+
update_config!(get_config, keys, value)
|
69
|
+
elsif tokens.length == 2
|
70
|
+
# read values from command args
|
71
|
+
keys = tokens.shift.to_s.strip.split('.')
|
72
|
+
value = tokens.shift.to_s.strip
|
73
|
+
|
74
|
+
update_config!(get_config, keys, value)
|
75
|
+
else
|
76
|
+
show_set_usage
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def run_get
|
81
|
+
if tokens.length == 1
|
82
|
+
# read key
|
83
|
+
config = get_config
|
84
|
+
cur = config
|
85
|
+
keys = tokens.shift.to_s.strip.split('.')
|
86
|
+
while ! keys.empty?
|
87
|
+
key = keys.shift
|
88
|
+
if cur.has_key? key
|
89
|
+
cur = cur[key]
|
90
|
+
else
|
91
|
+
abort "ERROR: Not Found"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
# output
|
95
|
+
if cur.is_a? Hash
|
96
|
+
puts "keys = #{cur.keys.join(', ')}"
|
97
|
+
else
|
98
|
+
puts cur
|
99
|
+
end
|
100
|
+
else
|
101
|
+
show_get_usage
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def run_site
|
106
|
+
if tokens.length >= 1
|
107
|
+
type = next_token
|
108
|
+
case type
|
109
|
+
when "add"
|
110
|
+
run_site_add
|
111
|
+
when "rm"
|
112
|
+
run_site_remove
|
113
|
+
else
|
114
|
+
show_site_usage
|
115
|
+
end
|
116
|
+
else
|
117
|
+
show_site_usage
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def run_site_remove
|
122
|
+
# git-contest-config site rm
|
123
|
+
if tokens.length == 1
|
124
|
+
# TODO: to check not found
|
125
|
+
site_name = tokens.shift.to_s.strip
|
126
|
+
|
127
|
+
puts "Are you sure you want to remove `#{site_name}`?"
|
128
|
+
this_is_yes = terminal.ask("when you remove the site, type `yes` > ").to_s
|
129
|
+
|
130
|
+
if this_is_yes == "yes"
|
131
|
+
# update config
|
132
|
+
config = get_config
|
133
|
+
config["sites"].delete site_name
|
134
|
+
# save config
|
135
|
+
File.open($git_contest_config, 'w') {|f| f.write config.to_yaml }
|
136
|
+
puts ""
|
137
|
+
puts "updated successfully!!"
|
138
|
+
puts ""
|
139
|
+
else
|
140
|
+
puts ""
|
141
|
+
puts "operation cancelled"
|
142
|
+
puts ""
|
143
|
+
end
|
144
|
+
else
|
145
|
+
show_site_rm_usage
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def run_site_add
|
150
|
+
# git-contest-config site add
|
151
|
+
if tokens.length == 1
|
152
|
+
puts "# input site config (password will be hidden)"
|
153
|
+
|
154
|
+
# read info
|
155
|
+
site_name = next_token
|
156
|
+
config = get_config
|
157
|
+
|
158
|
+
# init config
|
159
|
+
config["sites"][site_name] = {}
|
160
|
+
|
161
|
+
# input site info
|
162
|
+
# TODO: to check not found
|
163
|
+
config["sites"][site_name]["driver"] = terminal.ask("%10s > " % "driver").to_s
|
164
|
+
# TODO: to depend on above driver
|
165
|
+
config["sites"][site_name]["user"] = terminal.ask("%10s > " % "user id").to_s
|
166
|
+
config["sites"][site_name]["password"] = terminal.ask("%10s > " % "password") do |q|
|
167
|
+
unless /mswin(?!ce)|mingw|cygwin|bccwin/ === RUBY_PLATFORM
|
168
|
+
q.echo = "*"
|
169
|
+
end
|
170
|
+
end.to_s
|
171
|
+
|
172
|
+
# set config
|
173
|
+
File.open($git_contest_config, 'w') {|f| f.write config.to_yaml }
|
174
|
+
|
175
|
+
puts ""
|
176
|
+
puts "updated successfully!!"
|
177
|
+
puts ""
|
178
|
+
else
|
179
|
+
show_site_add_usage
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def show_get_usage
|
184
|
+
puts ""\
|
185
|
+
"usage: git contest config get [key]\n"\
|
186
|
+
"\n"\
|
187
|
+
"Example Usage:\n"\
|
188
|
+
" $ git contest config get key1\n"\
|
189
|
+
" $ git contest config get namespace1.key1\n"\
|
190
|
+
" $ git contest config get sites.some_judge.user\n"\
|
191
|
+
" \n"
|
192
|
+
end
|
193
|
+
|
194
|
+
def show_set_usage
|
195
|
+
puts ""\
|
196
|
+
"usage: git contest config set [key] <value>\n"\
|
197
|
+
"\n"\
|
198
|
+
"Example Usage:\n"\
|
199
|
+
" $ git contest config set key1 value1\n"\
|
200
|
+
" -> key1 = value1\n"\
|
201
|
+
" $ git contest config set key1\n"\
|
202
|
+
" -> set value from command-line\n"\
|
203
|
+
" $ git contest config set namespace1.key1 value1\n"\
|
204
|
+
" $ git contest config set sites.some_judge.user username\n"\
|
205
|
+
" \n"
|
206
|
+
end
|
207
|
+
|
208
|
+
def show_site_usage
|
209
|
+
puts ""\
|
210
|
+
"usage: git contest config site <type>\n"\
|
211
|
+
"\n"\
|
212
|
+
"Available types are:\n"\
|
213
|
+
" %-8s: add site\n"\
|
214
|
+
" \n" % ["add"]
|
215
|
+
end
|
216
|
+
|
217
|
+
def show_site_add_usage
|
218
|
+
puts ""\
|
219
|
+
"usage: git contest config site add <site-name>\n"\
|
220
|
+
"\n"\
|
221
|
+
"Example Usage:\n"\
|
222
|
+
" $ git contest config site add site1\n"\
|
223
|
+
" -> input information\n"\
|
224
|
+
" \n"
|
225
|
+
end
|
226
|
+
|
227
|
+
def show_site_rm_usage
|
228
|
+
puts ""\
|
229
|
+
"usage: git contest config site rm <site-name>\n"\
|
230
|
+
"\n"\
|
231
|
+
"Example Usage:\n"\
|
232
|
+
" $ git contest config site rm site1\n"\
|
233
|
+
" \n"
|
234
|
+
end
|
235
|
+
|
236
|
+
# Get Banner Text
|
237
|
+
def get_banner
|
238
|
+
""\
|
239
|
+
"usage: git contest config [type]\n"\
|
240
|
+
"\n"\
|
241
|
+
"Available types are:\n"\
|
242
|
+
" %-8s: set value\n"\
|
243
|
+
" %-8s: get value\n"\
|
244
|
+
" %-8s: set site info\n"\
|
245
|
+
" \n" % ["set", "get", "site"]
|
246
|
+
end
|
247
|
+
|
248
|
+
# Show Banner
|
249
|
+
def usage
|
250
|
+
puts get_banner
|
251
|
+
return 0
|
252
|
+
end
|
253
|
+
|
254
|
+
end # ConfigCommand
|
255
|
+
|
256
|
+
end # SubCommands
|
257
|
+
|
258
|
+
end # CommandLine
|