codersdojo 1.3.01 → 1.4.00

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.
@@ -3,11 +3,13 @@ require 'runner'
3
3
  require 'shell_argument_exception'
4
4
  require 'shell_wrapper'
5
5
  require 'console_view'
6
+ require 'state_reader'
6
7
  require 'help_command'
7
8
  require 'xhelp_command'
8
9
  require 'generate_command'
9
10
  require 'init_session_command'
10
11
  require 'capture_single_run_command'
12
+ require 'revert_to_green_command'
11
13
  require 'upload_command'
12
14
  require 'upload_no_open_command'
13
15
  require 'start_command'
@@ -15,6 +17,7 @@ require 'start_command'
15
17
  class ArgumentParser
16
18
 
17
19
  def initialize shell, view, scaffolder, hostname
20
+ meta_config_file = MetaConfigFile.new shell
18
21
  @help_command = HelpCommand.new view
19
22
  @xhelp_command = XHelpCommand.new view
20
23
  @generate_command = GenerateCommand.new shell, view, scaffolder
@@ -22,9 +25,11 @@ class ArgumentParser
22
25
  @upload_no_open_command = UploadNoOpenCommand.new @upload_command
23
26
  @init_session_command = InitSessionCommand.new shell, view
24
27
  @capture_single_run_command = CaptureSingleRunCommand.new shell, view
25
- @start_command = StartCommand.new shell, view, @upload_command
28
+ @revert_to_green_command = RevertToGreenCommand.new shell, view, meta_config_file, StateReader.new(shell)
29
+ @start_command = StartCommand.new shell, view, [@upload_command, @revert_to_green_command]
26
30
  @commands = [@help_command, @xhelp_command, @generate_command, @init_session_command,
27
- @capture_single_run_command, @start_command, @upload_command, @upload_no_open_command]
31
+ @capture_single_run_command, @start_command, @revert_to_green_command,
32
+ @upload_command, @upload_no_open_command]
28
33
  end
29
34
 
30
35
  def parse params
@@ -28,5 +28,9 @@ class CaptureSingleRunCommand
28
28
  def accepts_shell_command? command
29
29
  command == COMMAND_NAME
30
30
  end
31
+
32
+ def continue_test_loop?
33
+ false
34
+ end
31
35
 
32
36
  end
data/app/console_view.rb CHANGED
@@ -180,6 +180,14 @@ helptext
180
180
  show result
181
181
  end
182
182
 
183
+ def show_revert_to_step step
184
+ show "Revert to step #{step}."
185
+ end
186
+
187
+ def show_no_green_state_to_revert_to
188
+ show "Sorry, no previous green state to revert to."
189
+ end
190
+
183
191
  def show_socket_error command
184
192
  show "Encountered network error while <#{command}>. Is http://www.codersdojo.com down?"
185
193
  end
@@ -194,6 +202,7 @@ helptext
194
202
  show <<-msg
195
203
 
196
204
  You finished your kata. Choose your next action:
205
+ g) Revert to last green state.
197
206
  u) Upload the kata to http://www.codersdojo.com.
198
207
  e) Exit without uploading.
199
208
  r) Resume the kata.
data/app/filename.rb ADDED
@@ -0,0 +1,61 @@
1
+ class Filename
2
+
3
+ DIR_SEPARATOR = '/'
4
+ WINDOWS_DIR_SEPARATOR = '\\'
5
+
6
+ attr_accessor :path_items
7
+
8
+ def initialize filename
9
+ filename = filename.gsub(WINDOWS_DIR_SEPARATOR, DIR_SEPARATOR)
10
+ @path_items = filename.split(DIR_SEPARATOR).delete_if{|item| item.empty?}
11
+ @absolute_path = filename.start_with? DIR_SEPARATOR
12
+ end
13
+
14
+ def absolute_path?
15
+ @absolute_path
16
+ end
17
+
18
+ def relative_path?
19
+ not absolute_path?
20
+ end
21
+
22
+ def without_extension
23
+ if @path_items.size > 0 and @path_items.last.include? '.' then
24
+ Filename.new(to_s.split('.')[0..-2].join('.'))
25
+ else
26
+ clone
27
+ end
28
+ end
29
+
30
+ def extract_last_path_item
31
+ Filename.new(nil_to_empty_string @path_items.last)
32
+ end
33
+
34
+ def remove_last_path_item
35
+ Filename.new(make_string(@path_items[0..-2]))
36
+ end
37
+
38
+ def to_unix_s
39
+ make_string @path_items
40
+ end
41
+
42
+ def to_windows_s
43
+ make_string @path_items, WINDOWS_DIR_SEPARATOR
44
+ end
45
+
46
+ def to_s
47
+ to_unix_s
48
+ end
49
+
50
+ private
51
+
52
+ def make_string the_path_items, seperator=DIR_SEPARATOR
53
+ prefix = absolute_path? ? seperator : ''
54
+ prefix + the_path_items.join(seperator)
55
+ end
56
+
57
+ def nil_to_empty_string object
58
+ object.nil? ? "" : object
59
+ end
60
+
61
+ end
@@ -1,9 +1,12 @@
1
+ require 'shell_wrapper'
2
+
1
3
  class FilenameFormatter
2
4
 
3
5
  CODERSDOJO_WORKSPACE = ".codersdojo"
4
6
  RESULT_FILE = "result.txt"
5
7
  INFO_FILE = "info.yml"
6
8
  STATE_DIR_PREFIX = "state_"
9
+ DIR_SEPARATOR = '/'
7
10
 
8
11
  def self.state_dir_prefix
9
12
  STATE_DIR_PREFIX
@@ -14,7 +17,7 @@ class FilenameFormatter
14
17
  end
15
18
 
16
19
  def source_file_in_state_dir? file
17
- file = extract_last_path_item file
20
+ file = Filename.new(file).extract_last_path_item.to_s
18
21
  file != '..' and file != '.' and file != INFO_FILE and file != RESULT_FILE
19
22
  end
20
23
 
@@ -27,12 +30,12 @@ class FilenameFormatter
27
30
  end
28
31
 
29
32
  def state_file state_dir, file
30
- "#{state_dir}/#{file}"
33
+ concat_path state_dir, file
31
34
  end
32
35
 
33
36
  def state_dir session_id, step
34
37
  session_directory = session_dir session_id
35
- "#{session_directory}/#{STATE_DIR_PREFIX}#{step}"
38
+ concat_path session_directory, "#{STATE_DIR_PREFIX}#{step}"
36
39
  end
37
40
 
38
41
  def step_number_from_state_dir state_dir
@@ -40,29 +43,13 @@ class FilenameFormatter
40
43
  end
41
44
 
42
45
  def session_dir session_id
43
- "#{CODERSDOJO_WORKSPACE}/#{session_id}"
46
+ concat_path CODERSDOJO_WORKSPACE, session_id
44
47
  end
45
48
 
46
- def without_extension filename
47
- if filename.include? '.' then
48
- filename.split('.')[0..-2].join('.')
49
- else
50
- filename
51
- end
52
- end
53
-
54
- def extract_last_path_item dir_path
55
- last_separated_by_slash = dir_path.split('/').last
56
- last_separated_by_native = dir_path.split(ShellWrapper.new.dir_separator).last
57
- last = [last_separated_by_slash, last_separated_by_native].min_by {|item| item.nil? ? 0 : item.size}
58
- nil_to_empty_string last
49
+ def concat_path path, item
50
+ separator = path.end_with?(DIR_SEPARATOR) ? '' : DIR_SEPARATOR
51
+ "#{path}#{separator}#{item}"
59
52
  end
60
53
 
61
- private
62
-
63
- def nil_to_empty_string object
64
- object.nil? ? "" : object
65
- end
66
-
67
54
  end
68
55
 
@@ -26,5 +26,9 @@ class GenerateCommand
26
26
  def accepts_shell_command? command
27
27
  command == 'setup'
28
28
  end
29
+
30
+ def continue_test_loop?
31
+ false
32
+ end
29
33
 
30
34
  end
data/app/help_command.rb CHANGED
@@ -20,4 +20,8 @@ class HelpCommand
20
20
  ['help', '-h', '--help'].member? command
21
21
  end
22
22
 
23
+ def continue_test_loop?
24
+ false
25
+ end
26
+
23
27
  end
@@ -20,5 +20,9 @@ class InitSessionCommand
20
20
  def accepts_shell_command? command
21
21
  command == 'init-session'
22
22
  end
23
+
24
+ def continue_test_loop?
25
+ false
26
+ end
23
27
 
24
28
  end
@@ -0,0 +1,52 @@
1
+
2
+ class RevertToGreenCommand
3
+
4
+ def initialize shell, view, meta_config_file, state_reader
5
+ @shell = shell
6
+ @view = view
7
+ @meta_config_file = meta_config_file
8
+ @state_reader = state_reader
9
+ end
10
+
11
+ def execute_from_shell params
12
+ revert_to_green
13
+ end
14
+
15
+ def execute
16
+ revert_to_green
17
+ end
18
+
19
+ def revert_to_green
20
+ formatter = FilenameFormatter.new
21
+ @state_reader.session_dir = formatter.session_dir @shell.newest_dir_entry(FilenameFormatter.codersdojo_workspace)
22
+ @state_reader.goto_last_state
23
+ state = @state_reader.read_previous_state if @state_reader.state_exist?
24
+ while @state_reader.state_exist? and state.red?
25
+ state = @state_reader.read_previous_state
26
+ end
27
+ if @state_reader.state_exist? and state.green?
28
+ @view.show_revert_to_step @state_reader.next_step+1
29
+ @shell.rm_r @meta_config_file.source_files
30
+ state.files.each do |file|
31
+ dest_file = Filename.new(file).extract_last_path_item.to_s
32
+ @shell.write_file dest_file, @shell.read_file(file)
33
+ end
34
+ else
35
+ @view.show_no_green_state_to_revert_to
36
+ @state_reader.goto_last_state
37
+ end
38
+ end
39
+
40
+ def command_key
41
+ 'g'
42
+ end
43
+
44
+ def accepts_shell_command? command
45
+ command == 'revert-to-green'
46
+ end
47
+
48
+ def continue_test_loop?
49
+ true
50
+ end
51
+
52
+ end
data/app/scaffolder.rb CHANGED
@@ -32,7 +32,7 @@ class Scaffolder
32
32
 
33
33
  def scaffold template, kata_file
34
34
  @template_machine.placeholder_values['kata_file.ext'] = kata_file
35
- @template_machine.placeholder_values['kata_file'] = @filename_formatter.without_extension kata_file
35
+ @template_machine.placeholder_values['kata_file'] = Filename.new(kata_file).without_extension.to_s
36
36
  template = template == '???' ? ANY_TEMPLATE : template
37
37
  dir_path = "#{template_path}/#{template}"
38
38
  to_copy = @shell.real_dir_entries dir_path
data/app/scheduler.rb CHANGED
@@ -5,6 +5,7 @@ class Scheduler
5
5
  @view = view
6
6
  @last_action = ""
7
7
  @commands = commands
8
+ @continue_after_command = false
8
9
  end
9
10
 
10
11
  def start
@@ -24,11 +25,13 @@ class Scheduler
24
25
  end
25
26
 
26
27
  def interrupt_kata
28
+ @continue_after_command = false
27
29
  @view.show_kata_exit_message
28
30
  @last_action = @view.read_user_input.downcase
29
31
  @commands.each do |command|
30
32
  if @last_action.start_with? command.command_key
31
33
  command.execute
34
+ @continue_after_command = command.continue_test_loop?
32
35
  end
33
36
  end
34
37
  if last_action_was_exit? then
@@ -37,7 +40,7 @@ class Scheduler
37
40
  end
38
41
 
39
42
  def continue?
40
- @last_action == '' or last_action_was_resume?
43
+ @last_action == '' or last_action_was_resume? or @continue_after_command
41
44
  end
42
45
 
43
46
  def last_action_was_resume?
data/app/shell_wrapper.rb CHANGED
@@ -14,6 +14,12 @@ class ShellWrapper
14
14
  FileUtils.cp_r source, destination
15
15
  end
16
16
 
17
+ def rm_r file_regex
18
+ files_in_dir_tree('.', file_regex).each do |file|
19
+ FileUtils.rm file
20
+ end
21
+ end
22
+
17
23
  def mkdir dir
18
24
  FileUtils.mkdir dir
19
25
  end
data/app/start_command.rb CHANGED
@@ -3,11 +3,11 @@ require 'scheduler'
3
3
 
4
4
  class StartCommand
5
5
 
6
- def initialize shell, view, upload_command
6
+ def initialize shell, view, eval_loop_commands
7
7
  @shell = shell
8
8
  @view = view
9
9
  @meta_file = MetaConfigFile.new @shell
10
- @upload_command = upload_command
10
+ @eval_loop_commands = eval_loop_commands
11
11
  end
12
12
 
13
13
  def execute_from_shell params
@@ -21,7 +21,7 @@ class StartCommand
21
21
  runner = Runner.new @shell, SessionIdGenerator.new, @view
22
22
  runner.source_files = @meta_file.source_files
23
23
  runner.run_command = command
24
- scheduler = Scheduler.new runner, @view, [@upload_command]
24
+ scheduler = Scheduler.new runner, @view, @eval_loop_commands
25
25
  scheduler.start
26
26
  end
27
27
 
@@ -29,4 +29,8 @@ class StartCommand
29
29
  command == 'start'
30
30
  end
31
31
 
32
+ def continue_test_loop?
33
+ true
34
+ end
35
+
32
36
  end
data/app/state.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  class State
2
2
 
3
- attr_accessor :time, :files, :result, :return_code
3
+ attr_accessor :time, :files, :result, :return_code, :file_contents
4
4
 
5
- def initialize time=nil, files=nil, result=nil, return_code=nil
6
- @time = time
7
- @files = files
8
- @result = result
9
- @return_code = return_code
10
- end
5
+ def green?
6
+ @return_code == 0
7
+ end
8
+
9
+ def red?
10
+ not green?
11
+ end
11
12
 
12
13
  end
data/app/state_reader.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'info_property_file'
2
+ require 'filename'
2
3
  require 'filename_formatter'
3
4
  require 'state'
4
5
 
@@ -18,7 +19,7 @@ class StateReader
18
19
 
19
20
  def session_dir= session_dir
20
21
  @session_dir = session_dir
21
- @session_id = @filename_formatter.extract_last_path_item @session_dir
22
+ @session_id = Filename.new(@session_dir).extract_last_path_item.to_s
22
23
  end
23
24
 
24
25
  def state_count
@@ -33,32 +34,57 @@ class StateReader
33
34
  2
34
35
  end
35
36
 
36
- def get_state_dir
37
- @filename_formatter.state_dir(@session_id, @next_step)
37
+ def get_state_dir step=@next_step
38
+ @filename_formatter.state_dir(@session_id, step)
38
39
  end
39
40
 
40
41
  def has_next_state
41
- File.exist?(get_state_dir)
42
+ state_exist? @next_step
42
43
  end
43
44
 
44
- def read_next_state
45
- state = State.new
45
+ def state_exist? step=@next_step
46
+ File.exist?(get_state_dir step)
47
+ end
48
+
49
+ def goto_last_state
50
+ step = 0
51
+ while state_exist?(step) do step += 1 end
52
+ @next_step = step-1
53
+ end
54
+
55
+ def read_state
56
+ state = State.new
46
57
  state_dir = get_state_dir
47
58
  state.time = @shell.creation_time state_dir
48
- state.files = read_source_files state_dir
59
+ state.files = read_source_files state_dir
60
+ state.file_contents = read_source_file_contents state.files
49
61
  state.result = @shell.read_file @filename_formatter.result_file(state_dir)
50
62
  properties = @shell.read_properties @filename_formatter.info_file(state_dir)
51
63
  fill_state_with_properties state, properties
64
+ state
65
+ end
66
+
67
+ def read_next_state
68
+ state = read_state
52
69
  @next_step += 1
53
70
  state
54
71
  end
55
72
 
73
+ def read_previous_state
74
+ state = read_state
75
+ @next_step -= 1
76
+ state
77
+ end
78
+
56
79
  def read_source_files state_dir
57
80
  files = @shell.files_in_dir_tree state_dir
58
- source_files = files.find_all{|file| @filename_formatter.source_file_in_state_dir? file}
81
+ files.find_all{|file| @filename_formatter.source_file_in_state_dir? file}
82
+ end
83
+
84
+ def read_source_file_contents source_files
59
85
  marker = "=========="
60
86
  source_files.collect {|file|
61
- filename = @filename_formatter.extract_last_path_item file
87
+ filename = Filename.new(file).extract_last_path_item.to_s
62
88
  code = @shell.read_file(file)
63
89
  "#{marker} #{filename} #{marker}\n\n#{code}"
64
90
  }
@@ -25,7 +25,7 @@ class UploadCommand
25
25
  formatter = FilenameFormatter.new
26
26
  framework = @meta_file.framework_property
27
27
  if not session_directory then
28
- session_directory = formatter.session_dir @shell.newest_dir_entry(FilenameFormatter.codersdojo_workspace)
28
+ session_directory = formatter.session_dir @shell.newest_dir_entry(FilenameFormatter.codersdojo_workspace)
29
29
  end
30
30
  @view.show_upload_start session_directory, @hostname, framework
31
31
  @uploader.framework = framework
@@ -45,5 +45,9 @@ class UploadCommand
45
45
  def accepts_shell_command? command
46
46
  command == 'upload'
47
47
  end
48
-
48
+
49
+ def continue_test_loop?
50
+ false
51
+ end
52
+
49
53
  end
@@ -16,4 +16,8 @@ class UploadNoOpenCommand
16
16
  command == 'upload-no-open'
17
17
  end
18
18
 
19
+ def continue_test_loop?
20
+ false
21
+ end
22
+
19
23
  end
data/app/uploader.rb CHANGED
@@ -47,7 +47,7 @@ class Uploader
47
47
  kata_data = {:framework => @framework}
48
48
  states_data = states.each_with_index do |state,index|
49
49
  green = state.return_code == 0
50
- kata_data["states[#{index}]"] = {:code => state.files, :result => state.result, :green => green,
50
+ kata_data["states[#{index}]"] = {:code => state.file_contents, :result => state.result, :green => green,
51
51
  :created_at => state.time}
52
52
  end
53
53
  RestClient.post "#{@hostname}#{@@kata_path}", kata_data
@@ -0,0 +1,13 @@
1
+ ; Adapt the code to your code kata %kata_file%.
2
+
3
+ (ns %kata_file%
4
+ (:use [midje.sweet]))
5
+
6
+ (use 'clojure.test)
7
+
8
+ (defn %kata_file% []
9
+ "fixme")
10
+
11
+ (fact (%kata_file%) => "foo")
12
+
13
+ (run-tests)
@@ -0,0 +1,3 @@
1
+ framework: clojure.midje
2
+ source_files: .*\.clj
3
+
@@ -0,0 +1,12 @@
1
+ These files were created:
2
+ README is what you are currently reading
3
+ run-once.%sh% runs your tests once
4
+ run-endless.%sh% runs your tests endlessly via run-once.%sh%
5
+
6
+ Run run-endless.%sh% and start your kata. (On Mac/Linux you have to call ./run-endless.%sh%.)
7
+
8
+ Assumptions:
9
+ - Java is installed on your system and 'java' is in the path.
10
+ - clojure.jar, clojure-contrib.jar, midje.jar and unifycle.jar are placed in the 'lib' directory.
11
+
12
+ The support for Clojure/Midje was contributed by Stefan Roock.
File without changes
@@ -0,0 +1,7 @@
1
+ (defproject %kata_file% "0.1"
2
+ :dependencies [[org.clojure/clojure
3
+ "1.1.0-master-SNAPSHOT"]
4
+ [org.clojure/clojure-contrib
5
+ "1.0-SNAPSHOT"]
6
+ [lein-midje "1.0.1"]]
7
+ :main %kata_file%)
@@ -0,0 +1,2 @@
1
+ codersdojo start run-once.%sh%
2
+
@@ -0,0 +1 @@
1
+ java -cp lib/clojure-contrib.jar%:%lib/clojure.jar%:%lib/midje.jar%:%lib/unifycle.jar clojure.main %kata_file%.clj
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codersdojo
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 3
9
- - 1
10
- version: 1.3.01
8
+ - 4
9
+ - 0
10
+ version: 1.4.00
11
11
  platform: ruby
12
12
  authors:
13
13
  - CodersDojo-Team
@@ -15,13 +15,29 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-02 00:00:00 +02:00
18
+ date: 2011-07-30 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: rest-client
22
+ name: json
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 1
32
+ - 4
33
+ - 6
34
+ version: 1.4.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rest-client
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
25
41
  none: false
26
42
  requirements:
27
43
  - - ">="
@@ -33,11 +49,11 @@ dependencies:
33
49
  - 1
34
50
  version: 1.6.1
35
51
  type: :runtime
36
- version_requirements: *id001
52
+ version_requirements: *id002
37
53
  - !ruby/object:Gem::Dependency
38
54
  name: term-ansicolor
39
55
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
56
+ requirement: &id003 !ruby/object:Gem::Requirement
41
57
  none: false
42
58
  requirements:
43
59
  - - ">="
@@ -49,7 +65,7 @@ dependencies:
49
65
  - 5
50
66
  version: 1.0.5
51
67
  type: :runtime
52
- version_requirements: *id002
68
+ version_requirements: *id003
53
69
  description: Client executes tests in an endless loop and logs source code and test result for later uplaod.
54
70
  email: codersdojo@it-agile.de
55
71
  executables:
@@ -63,6 +79,7 @@ files:
63
79
  - app/capture_single_run_command.rb
64
80
  - app/codersdojo.rb
65
81
  - app/console_view.rb
82
+ - app/filename.rb
66
83
  - app/filename_formatter.rb
67
84
  - app/generate_command.rb
68
85
  - app/help_command.rb
@@ -71,6 +88,7 @@ files:
71
88
  - app/meta_config_file.rb
72
89
  - app/progress.rb
73
90
  - app/property_file_missing_exception.rb
91
+ - app/revert_to_green_command.rb
74
92
  - app/runner.rb
75
93
  - app/scaffolder.rb
76
94
  - app/scheduler.rb
@@ -96,6 +114,12 @@ files:
96
114
  - templates/clojure.is-test/README
97
115
  - templates/clojure.is-test/run-endless.%sh%
98
116
  - templates/clojure.is-test/run-once.%sh%
117
+ - templates/clojure.midje/%kata_file%.clj
118
+ - templates/clojure.midje/lib/place_your_libs_here
119
+ - templates/clojure.midje/project.clj
120
+ - templates/clojure.midje/README
121
+ - templates/clojure.midje/run-endless.%sh%
122
+ - templates/clojure.midje/run-once.%sh%
99
123
  - templates/cpp.gtest/%Kata_file%.cc
100
124
  - templates/cpp.gtest/Makefile
101
125
  - templates/cpp.gtest/README
@@ -171,6 +195,7 @@ files:
171
195
  - templates/shell.shunit/run-once.%sh%
172
196
  - templates/any/.meta
173
197
  - templates/clojure.is-test/.meta
198
+ - templates/clojure.midje/.meta
174
199
  - templates/cpp.gtest/.meta
175
200
  - templates/csharp.nunit.dotnet/.meta
176
201
  - templates/csharp.nunit.mono/.meta