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.
@@ -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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'bcpm'
4
+
5
+ Bcpm::CLI.run ARGV
@@ -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'
@@ -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
@@ -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
@@ -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