bcpm 0.11
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.
- data/CHANGELOG +133 -0
- data/Manifest +23 -0
- data/README +292 -0
- data/Rakefile +23 -0
- data/bcpm.gemspec +35 -0
- data/bin/bcpm +5 -0
- data/lib/bcpm.rb +23 -0
- data/lib/bcpm/cleanup.rb +24 -0
- data/lib/bcpm/cli.rb +262 -0
- data/lib/bcpm/config.rb +100 -0
- data/lib/bcpm/dist.rb +133 -0
- data/lib/bcpm/duel.rb +153 -0
- data/lib/bcpm/git.rb +93 -0
- data/lib/bcpm/match.rb +275 -0
- data/lib/bcpm/player.rb +410 -0
- data/lib/bcpm/regen.rb +102 -0
- data/lib/bcpm/socket.rb +8 -0
- data/lib/bcpm/tests/assertion_error.rb +13 -0
- data/lib/bcpm/tests/assertions.rb +102 -0
- data/lib/bcpm/tests/case_base.rb +166 -0
- data/lib/bcpm/tests/environment.rb +256 -0
- data/lib/bcpm/tests/suite.rb +114 -0
- data/lib/bcpm/tests/test_match.rb +166 -0
- data/lib/bcpm/update.rb +38 -0
- metadata +129 -0
data/bcpm.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{bcpm}
|
5
|
+
s.version = "0.11"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Victor Costan"]
|
9
|
+
s.date = %q{2011-01-26}
|
10
|
+
s.default_executable = %q{bcpm}
|
11
|
+
s.description = %q{Battlecode (MIT 6.370) package manager.}
|
12
|
+
s.email = %q{victor@costan.us}
|
13
|
+
s.executables = ["bcpm"]
|
14
|
+
s.extra_rdoc_files = ["CHANGELOG", "README", "bin/bcpm", "lib/bcpm.rb", "lib/bcpm/cleanup.rb", "lib/bcpm/cli.rb", "lib/bcpm/config.rb", "lib/bcpm/dist.rb", "lib/bcpm/duel.rb", "lib/bcpm/git.rb", "lib/bcpm/match.rb", "lib/bcpm/player.rb", "lib/bcpm/regen.rb", "lib/bcpm/socket.rb", "lib/bcpm/tests/assertion_error.rb", "lib/bcpm/tests/assertions.rb", "lib/bcpm/tests/case_base.rb", "lib/bcpm/tests/environment.rb", "lib/bcpm/tests/suite.rb", "lib/bcpm/tests/test_match.rb", "lib/bcpm/update.rb"]
|
15
|
+
s.files = ["CHANGELOG", "Manifest", "README", "Rakefile", "bin/bcpm", "lib/bcpm.rb", "lib/bcpm/cleanup.rb", "lib/bcpm/cli.rb", "lib/bcpm/config.rb", "lib/bcpm/dist.rb", "lib/bcpm/duel.rb", "lib/bcpm/git.rb", "lib/bcpm/match.rb", "lib/bcpm/player.rb", "lib/bcpm/regen.rb", "lib/bcpm/socket.rb", "lib/bcpm/tests/assertion_error.rb", "lib/bcpm/tests/assertions.rb", "lib/bcpm/tests/case_base.rb", "lib/bcpm/tests/environment.rb", "lib/bcpm/tests/suite.rb", "lib/bcpm/tests/test_match.rb", "lib/bcpm/update.rb", "bcpm.gemspec"]
|
16
|
+
s.homepage = %q{http://git.pwnb.us/six370}
|
17
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Bcpm", "--main", "README"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubyforge_project = %q{bcpm}
|
20
|
+
s.rubygems_version = %q{1.3.7}
|
21
|
+
s.summary = %q{Battlecode (MIT 6.370) package manager.}
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_development_dependency(%q<echoe>, [">= 3.2"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<echoe>, [">= 3.2"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<echoe>, [">= 3.2"])
|
34
|
+
end
|
35
|
+
end
|
data/bin/bcpm
ADDED
data/lib/bcpm.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Battlecode package manager.
|
2
|
+
#
|
3
|
+
# See the README for a reference on the command-line interface.
|
4
|
+
module Bcpm
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'bcpm/cleanup.rb'
|
8
|
+
require 'bcpm/cli.rb'
|
9
|
+
require 'bcpm/config.rb'
|
10
|
+
require 'bcpm/dist.rb'
|
11
|
+
require 'bcpm/duel.rb'
|
12
|
+
require 'bcpm/git.rb'
|
13
|
+
require 'bcpm/match.rb'
|
14
|
+
require 'bcpm/player.rb'
|
15
|
+
require 'bcpm/regen.rb'
|
16
|
+
require 'bcpm/socket.rb'
|
17
|
+
require 'bcpm/tests/assertions.rb'
|
18
|
+
require 'bcpm/tests/assertion_error.rb'
|
19
|
+
require 'bcpm/tests/case_base.rb'
|
20
|
+
require 'bcpm/tests/environment.rb'
|
21
|
+
require 'bcpm/tests/suite.rb'
|
22
|
+
require 'bcpm/tests/test_match.rb'
|
23
|
+
require 'bcpm/update.rb'
|
data/lib/bcpm/cleanup.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module Bcpm
|
5
|
+
|
6
|
+
# Cleans up all the messes left behind by bcpm crashes.
|
7
|
+
module Cleanup
|
8
|
+
# Cleans up all the messes left behind by bcpm crashes.
|
9
|
+
def self.run
|
10
|
+
Bcpm::Player.list.each do |player|
|
11
|
+
Bcpm::Player.uninstall player if /^bcpmtest/ =~ player
|
12
|
+
end
|
13
|
+
|
14
|
+
temp_path = File.join(Dir.tmpdir, 'bcpm')
|
15
|
+
return unless File.exist?(temp_path)
|
16
|
+
Dir.entries(temp_path).each do |entry|
|
17
|
+
next if ['.', '..'].include? entry
|
18
|
+
path = File.join temp_path, entry
|
19
|
+
FileUtils.rm_rf path if File.directory? path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end # module Bcpm::Cleanup
|
23
|
+
|
24
|
+
end # namespace Bcpm
|
data/lib/bcpm/cli.rb
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module Bcpm
|
5
|
+
|
6
|
+
# Command-line interface.
|
7
|
+
module CLI
|
8
|
+
# Entry point for commands.
|
9
|
+
def self.run(args)
|
10
|
+
if args.length < 1
|
11
|
+
help
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
|
15
|
+
case args.first
|
16
|
+
when 'self', 'gem' # Upgrade bcpm.
|
17
|
+
Bcpm::Update.upgrade
|
18
|
+
when 'dist' # Install or upgrade the battlecode distribution.
|
19
|
+
Bcpm::Dist.upgrade
|
20
|
+
when 'reset' # Uninstalls the distribution and players, and removes the config file.
|
21
|
+
Bcpm::Cleanup.run
|
22
|
+
Bcpm::Player.uninstall_all
|
23
|
+
Bcpm::Dist.uninstall
|
24
|
+
Bcpm::Config.reset
|
25
|
+
when 'install' # Add a player project to the workspace, from a git repository.
|
26
|
+
unless Bcpm::Dist.installed?
|
27
|
+
puts "Please install a battlecode distribution first!"
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
if args.length < 2
|
32
|
+
puts "Please supply the path to the player repository!"
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
exit 1 unless Bcpm::Player.install(args[1], args[2] || 'master')
|
36
|
+
when 'copy', 'copyplayer' # Create a new player project using an existing project as a template.
|
37
|
+
unless Bcpm::Dist.installed?
|
38
|
+
puts "Please install a battlecode distribution first!"
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
|
42
|
+
if args.length < 3
|
43
|
+
puts "Please supply the new player name, and the path to the template player repository!"
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
exit 1 unless Bcpm::Player.checkpoint(args[2], args[3] || 'master', args[1])
|
47
|
+
when 'new', 'newplayer' # Create a new player project from the built-in template.
|
48
|
+
unless Bcpm::Dist.installed?
|
49
|
+
puts "Please install a battlecode distribution first!"
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
|
53
|
+
if args.length < 2
|
54
|
+
puts "Please supply the new player name!"
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
exit 1 unless Bcpm::Player.create(args[1])
|
58
|
+
when 'uninstall', 'remove' # Remove a player project from the workspace.
|
59
|
+
unless Bcpm::Dist.installed?
|
60
|
+
puts "Please install a battlecode distribution first!"
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
|
64
|
+
if args.length < 2
|
65
|
+
puts "Please supply the player name!"
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
Bcpm::Player.uninstall args[1]
|
69
|
+
when 'rewire' # Re-write a player project's configuration files.
|
70
|
+
unless Bcpm::Dist.installed?
|
71
|
+
puts "Please install a battlecode distribution first!"
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
|
75
|
+
if args.length == 1
|
76
|
+
# Try using the current dir as the player name.
|
77
|
+
args[1, 0] = [File.basename(Dir.pwd)]
|
78
|
+
end
|
79
|
+
|
80
|
+
if args.length < 2
|
81
|
+
puts "Please supply the player name!"
|
82
|
+
exit 1
|
83
|
+
end
|
84
|
+
Bcpm::Player.reconfigure args[1]
|
85
|
+
when 'list', 'ls' # Displays the installed players.
|
86
|
+
unless Bcpm::Dist.installed?
|
87
|
+
puts "Please install a battlecode distribution first!"
|
88
|
+
exit 1
|
89
|
+
end
|
90
|
+
puts Bcpm::Player.list_active.sort.join("\n")
|
91
|
+
when 'match', 'livematch', 'debugmatch', 'debug' # Run a match in live or headless mode.
|
92
|
+
unless Bcpm::Dist.installed?
|
93
|
+
puts "Please install a battlecode distribution first!"
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
|
97
|
+
if args.length == 3
|
98
|
+
# Try using the current dir as a player name.
|
99
|
+
args[1, 0] = [File.basename(Dir.pwd)]
|
100
|
+
end
|
101
|
+
|
102
|
+
if args.length < 4
|
103
|
+
puts "Please supply the player names and the map name!"
|
104
|
+
exit 1
|
105
|
+
end
|
106
|
+
mode = if args[0][0, 4] == 'live'
|
107
|
+
:live
|
108
|
+
elsif args[0][0, 5] == 'debug'
|
109
|
+
:debug
|
110
|
+
else
|
111
|
+
:file
|
112
|
+
end
|
113
|
+
puts Bcpm::Match.run(args[1], args[2], args[3], mode)
|
114
|
+
when 'duel' # Have two players fight it out on all maps.
|
115
|
+
if args.length < 3
|
116
|
+
puts "Pleas supply the player names!"
|
117
|
+
exit 1
|
118
|
+
end
|
119
|
+
if args.length >= 4
|
120
|
+
maps = args[3..-1]
|
121
|
+
else
|
122
|
+
maps = nil
|
123
|
+
end
|
124
|
+
outcome = Bcpm::Duel.duel_pair args[1], args[2], true, maps
|
125
|
+
puts "#{'%+3d' % outcome[:score]} points, " +
|
126
|
+
"#{'%3d' % outcome[:wins].length} wins, " +
|
127
|
+
" #{'%3d' % outcome[:losses].length} losses, " +
|
128
|
+
"#{'%3d' % outcome[:errors].length} errors"
|
129
|
+
when 'rank' # Ranks all the players.
|
130
|
+
if args.length < 2
|
131
|
+
players = Bcpm::Player.list_active.sort
|
132
|
+
else
|
133
|
+
players = args[1..-1]
|
134
|
+
end
|
135
|
+
outcome = Bcpm::Duel.rank_players players, true
|
136
|
+
outcome.each { |score, player| print "%+4d %s\n" % [score, player] }
|
137
|
+
when 'pit' # Pits one player against all the other players.
|
138
|
+
if args.length < 2
|
139
|
+
puts "Please supply a player name!"
|
140
|
+
end
|
141
|
+
player = args[1]
|
142
|
+
if args.length >= 3
|
143
|
+
enemies = args[2..-1]
|
144
|
+
else
|
145
|
+
enemies = Bcpm::Player.list_active.sort - [player]
|
146
|
+
end
|
147
|
+
outcome = Bcpm::Duel.score_player player, enemies, true
|
148
|
+
puts "#{'%+4d' % outcome[:points]} points"
|
149
|
+
outcome[:scores].each do |score, player|
|
150
|
+
print "%+4d vs %s\n" % [score, player]
|
151
|
+
end
|
152
|
+
when 'replay' # Replay a match using its binlog (.rms file).
|
153
|
+
unless Bcpm::Dist.installed?
|
154
|
+
puts "Please install a battlecode distribution first!"
|
155
|
+
exit 1
|
156
|
+
end
|
157
|
+
|
158
|
+
if args.length == 1
|
159
|
+
# Replay the last game.
|
160
|
+
replays = Bcpm::Tests::TestMatch.stashed_replays
|
161
|
+
args[1, 0] = [replays.max] unless replays.empty?
|
162
|
+
end
|
163
|
+
|
164
|
+
if args.length < 2
|
165
|
+
puts "Please supply the path to the match binlog (.rms file)!"
|
166
|
+
exit 1
|
167
|
+
end
|
168
|
+
Bcpm::Match.replay args[1]
|
169
|
+
when 'test' # Run the entire test suite against a player.
|
170
|
+
unless Bcpm::Dist.installed?
|
171
|
+
puts "Please install a battlecode distribution first!"
|
172
|
+
exit 1
|
173
|
+
end
|
174
|
+
|
175
|
+
if args.length == 1
|
176
|
+
# Try using the current dir as the player name.
|
177
|
+
args[1, 0] = [File.basename(Dir.pwd)]
|
178
|
+
end
|
179
|
+
|
180
|
+
if args.length < 2
|
181
|
+
puts "Please supply the player name!"
|
182
|
+
exit 1
|
183
|
+
end
|
184
|
+
Bcpm::Player.run_suite args[1]
|
185
|
+
when 'case', 'testcase', 'livecase', 'live' # Run a single testcase against a player.
|
186
|
+
unless Bcpm::Dist.installed?
|
187
|
+
puts "Please install a battlecode distribution first!"
|
188
|
+
exit 1
|
189
|
+
end
|
190
|
+
|
191
|
+
if args.length == 2
|
192
|
+
# Try using the current dir as the player name.
|
193
|
+
args[1, 0] = [File.basename(Dir.pwd)]
|
194
|
+
end
|
195
|
+
|
196
|
+
if args.length < 3
|
197
|
+
puts "Please supply the player name and the testcase name!"
|
198
|
+
exit 1
|
199
|
+
end
|
200
|
+
Bcpm::Player.run_case args[2], args[0][0, 4] == 'live', args[1]
|
201
|
+
|
202
|
+
when 'clean', 'cleanup' # Removes all temporaries left behind by crashes.
|
203
|
+
Bcpm::Cleanup.run
|
204
|
+
|
205
|
+
when 'config', 'set'
|
206
|
+
if args.length < 2
|
207
|
+
Bcpm::Config.print_config
|
208
|
+
else
|
209
|
+
Bcpm::Config.ui_set(args[1], args[2])
|
210
|
+
end
|
211
|
+
|
212
|
+
when 'regen' # Regenerates automatically generated source code.
|
213
|
+
if args.length < 2
|
214
|
+
puts "Please supply the source file(s)."
|
215
|
+
exit 1
|
216
|
+
end
|
217
|
+
Bcpm::Regen.run args[1..-1]
|
218
|
+
|
219
|
+
when 'lsmaps', 'lsmap', 'maps', 'map' # Lists the maps in the distribution.
|
220
|
+
unless Bcpm::Dist.installed?
|
221
|
+
puts "Please install a battlecode distribution first!"
|
222
|
+
exit 1
|
223
|
+
end
|
224
|
+
puts Bcpm::Dist.maps.sort.join("\n")
|
225
|
+
when 'copymap', 'cpmap' # Clones a distribution map for testing.
|
226
|
+
unless Bcpm::Dist.installed?
|
227
|
+
puts "Please install a battlecode distribution first!"
|
228
|
+
exit 1
|
229
|
+
end
|
230
|
+
if args.length < 2
|
231
|
+
puts "Please supply the map name and destination"
|
232
|
+
exit 1
|
233
|
+
end
|
234
|
+
if args.length < 3
|
235
|
+
# Default destination.
|
236
|
+
if File.exist?('suite') && File.directory?('suite')
|
237
|
+
FileUtils.mkdir_p 'maps'
|
238
|
+
args[2] = 'suite/maps'
|
239
|
+
else
|
240
|
+
puts "Please supply map destination or cd into a player directory"
|
241
|
+
exit 1
|
242
|
+
end
|
243
|
+
end
|
244
|
+
Bcpm::Dist.copy_map args[1], args[2]
|
245
|
+
else
|
246
|
+
help
|
247
|
+
exit 1
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# Prints the CLI help.
|
252
|
+
def self.help
|
253
|
+
print <<END_HELP
|
254
|
+
Battlecode (MIT 6.470) package manager.
|
255
|
+
|
256
|
+
See the README file for usage instructions.
|
257
|
+
|
258
|
+
END_HELP
|
259
|
+
end
|
260
|
+
end # module Bcpm::CLI
|
261
|
+
|
262
|
+
end # namespace Bcpm
|
data/lib/bcpm/config.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module Bcpm
|
5
|
+
|
6
|
+
# Persistent, per-user bcpm configuration information.
|
7
|
+
module Config
|
8
|
+
# Hash-style access to the configuration dictionary.
|
9
|
+
def self.[](key)
|
10
|
+
config[key.to_sym]
|
11
|
+
end
|
12
|
+
|
13
|
+
# Hash-style access to configuration dictionary.
|
14
|
+
def self.[]=(key, new_value)
|
15
|
+
if new_value.nil?
|
16
|
+
config.delete key.to_sym
|
17
|
+
else
|
18
|
+
config[key.to_sym] = new_value
|
19
|
+
end
|
20
|
+
write_config
|
21
|
+
end
|
22
|
+
|
23
|
+
# The configuration dictionary.
|
24
|
+
def self.config
|
25
|
+
@config ||= read_config
|
26
|
+
end
|
27
|
+
|
28
|
+
# Reads the YAML configuration file.
|
29
|
+
def self.read_config
|
30
|
+
if File.exists? config_file
|
31
|
+
@config = File.open(config_file) { |f| YAML.load f }
|
32
|
+
else
|
33
|
+
@config = {}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Writes the configuration to the YAML file.
|
38
|
+
def self.write_config
|
39
|
+
File.open(config_file, 'wb') { |f| YAML.dump config, f }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Path to the configuration YAML file.
|
43
|
+
def self.config_file
|
44
|
+
File.expand_path '~/.bcpm_config'
|
45
|
+
end
|
46
|
+
|
47
|
+
# Removes the configuration YAML file and resets the configuration hash.
|
48
|
+
def self.reset
|
49
|
+
File.unlink config_file if File.exist?(config_file)
|
50
|
+
@config = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
# Outputs the configuration.
|
54
|
+
def self.print_config
|
55
|
+
config.keys.sort_by(&:to_s).each do |key|
|
56
|
+
print "#{key}: #{config[key]}\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Executes a config command from the UI.
|
61
|
+
def self.ui_set(key, value)
|
62
|
+
# Normalize values.
|
63
|
+
case value && value.downcase
|
64
|
+
when 'on', 'true'
|
65
|
+
value = true
|
66
|
+
when 'off', 'false'
|
67
|
+
value = false
|
68
|
+
end
|
69
|
+
|
70
|
+
# Process keys that include values.
|
71
|
+
prefix = key[0]
|
72
|
+
|
73
|
+
toggle = false
|
74
|
+
if [?+, ?-, ?^].include? prefix
|
75
|
+
key = key[1..-1]
|
76
|
+
case prefix
|
77
|
+
when ?+
|
78
|
+
value = true
|
79
|
+
when ?-
|
80
|
+
value = false
|
81
|
+
when ?^
|
82
|
+
toggle = true
|
83
|
+
end
|
84
|
+
self[key]
|
85
|
+
end
|
86
|
+
|
87
|
+
# Normalize keys.
|
88
|
+
key = key.downcase
|
89
|
+
|
90
|
+
# Execute the configuration change.
|
91
|
+
if toggle
|
92
|
+
self[key] = !self[key]
|
93
|
+
else
|
94
|
+
self[key] = value
|
95
|
+
end
|
96
|
+
print "#{key} set to #{value}\n"
|
97
|
+
end
|
98
|
+
end # module Bcpm::Config
|
99
|
+
|
100
|
+
end # namespace Bcpm
|