svn-command 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/ProjectInfo.rb CHANGED
@@ -5,7 +5,7 @@ module Project
5
5
  PrettyName = "Enhanced Subversion Command"
6
6
  Name = "svn-command"
7
7
  RubyForgeName = "svn-command"
8
- Version = "0.2.4"
8
+ Version = "0.2.5"
9
9
  Specification = Gem::Specification.new do |s|
10
10
  s.name = Project::Name
11
11
  s.summary = "A nifty wrapper command for Subversion's command-line svn client"
data/Readme CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  == Introduction
12
12
 
13
- This is a replacement <tt>svn</tt> <b>command-line client</b> meant to be used instead of the standard +svn+ command. Actually, it's a _wrapper_, not a replacement, because it still uses <tt>/usr/bin/svn</tt> to do all the dirty work.
13
+ This is a replacement <b><tt>svn</tt> command-line client</b> meant to be used instead of the standard +svn+ command. (Actually, it's a _wrapper_, not a replacement, because it still uses <tt>/usr/bin/svn</tt> to do all the dirty work.)
14
14
 
15
15
  == Installation
16
16
 
@@ -46,33 +46,70 @@ You'll know it's working by way of two signs:
46
46
  == Features
47
47
 
48
48
  Changes to existing subcommands:
49
- * <tt>svn diff</tt>
49
+ * <b><tt>svn diff</tt></b>
50
50
  * output is in _color_* (requires +colordiff+, see below)
51
51
  * <tt>svn diff</tt> includes the differences from your *externals* too (consistent with how <tt>svn status</tt> includes them) so that you don't forget to commit those changes too! (pass <tt>--ignore-externals</tt> if you _don't_ want a diff of externals)
52
- * <tt>svn status</tt>
52
+ * <b><tt>svn status</tt></b>
53
53
  * filters out distracting, useless output about externals (don't worry -- it still shows which files were _modified_)
54
54
  * the flags (?, M, C, etc.) are in *color*!
55
- * <tt>svn move</tt> it will let you move multiple source files to a destination directory with a single command
55
+ * <b><tt>svn move</tt></b> it will let you move multiple source files to a destination directory with a single command
56
56
 
57
57
  (* You can pass --no-color to disable colors for a single command...useful if you want to pipe the output to another command or something. Eventually maybe we could make this a per-user option via .svn-command?)
58
58
 
59
59
  New subcommands:
60
- * <tt>svn each_unadded</tt> (+eu+, +unadded+) -- goes through each unadded (<tt>?</tt>) file reported by <tt>svn status</tt> and asks you what to do with them (add, delete, ignore).
61
- * <tt>svn externals</tt> -- lists all externals
62
- * <tt>svn revisions</tt> -- lists all revisions with log messages and lets you browse through them interactively
63
- * <tt>svn edit_externals</tt> (+ee+)
64
- * <tt>svn externalize</tt>
65
- * <tt>svn set_message</tt> / <tt>svn get_message</tt> / <tt>svn edit_message</tt> -- shortcuts for accessing <tt>--revprop svn:log</tt>
66
- * <tt>svn ignore</tt> -- shortcut for accessing <tt>svn:ignore</tt> property
67
- * <tt>svn view_commits</tt> -- gives you output from both <tt>svn log</tt> and from <tt>svn diff</tt> for the given changesets (useful for code reviews)
68
- * <tt>svn repository_root</tt> -- prints out the root repository URL of the working copy you are in
69
- * <tt>svn delete_svn</tt> -- causes the current directory (recursively) to no longer be a working copy
60
+ * <b><tt>svn each_unadded</tt></b> (+eu+, +unadded+) -- goes through each unadded (<tt>?</tt>) file reported by <tt>svn status</tt> and asks you what to do with them (add, delete, ignore).
61
+ * <b><tt>svn revisions</tt></b> -- lists all revisions with log messages and lets you browse through them interactively
62
+ * <b><tt>svn externals</tt></b> -- lists all externals
63
+ * <b><tt>svn edit_externals</tt></b> (+ee+)
64
+ * <b><tt>svn externalize</tt></b>
65
+ * <b><tt>svn set_message</tt></b> / <tt>svn get_message</tt> / <tt>svn edit_message</tt> -- shortcuts for accessing <tt>--revprop svn:log</tt>
66
+ * <b><tt>svn ignore</tt></b> -- shortcut for accessing <tt>svn:ignore</tt> property
67
+ * <b><tt>svn view_commits</tt></b> -- gives you output from both <tt>svn log</tt> and from <tt>svn diff</tt> for the given changesets (useful for code reviews)
68
+ * <b><tt>svn url</tt></b> -- prints out the URL of the given working copy path or the curretn working copy
69
+ * <b><tt>svn repository_root</tt></b> -- prints out the root repository URL of the working copy you are in
70
+ * <b><tt>svn delete_svn</tt></b> -- causes the current directory (recursively) to no longer be a working copy
70
71
 
71
72
  (RDoc question: how do I make the identifiers like Subversion::SvnCommand#externalize into links??)
72
73
 
73
74
  = Usage / Examples
74
75
 
75
- == <tt>svn st</tt>
76
+ == <tt>svn each_unadded</tt>
77
+
78
+ My personal favorite. This command is useful for keeping your working copies clean -- getting rid of all those accumulated temp files (or *ignoring* or *adding* them if they're something that _all_ users of this repository should be aware of).
79
+
80
+ It simply goes through each "unadded" file (each file reporting a status of <tt>?</tt>) reported by <tt>svn status</tt> and asks you what you want to do with them -- *add*, *delete*, or *ignore*.
81
+
82
+ > svn each_unadded
83
+
84
+ What do you want to do with plugins/database_log4r/doc?
85
+ (shows preview)
86
+ (a)dd, (d)elete, add to svn:(i)ignore property, or [Enter] to do nothing > i
87
+ Ignoring...
88
+
89
+ What do you want to do with applications/underlord/db/schema.rb?
90
+ (shows preview)
91
+ (a)dd, (d)elete, add to svn:(i)ignore property, or [Enter] to do nothing > a
92
+ Adding...
93
+
94
+ What do you want to do with applications/underlord/vendor/plugins/exception_notification?
95
+ (shows preview)
96
+ (a)dd, (d)elete, add to svn:(i)ignore property, or [Enter] to do nothing > d
97
+ Are you pretty much *SURE* you want to 'rm -rf applications/underlord/vendor/plugins/exception_notification'? (y)es, (n)o > y
98
+ Deleting...
99
+
100
+ For *files*, it will show a preview of the _contents_ of that file (limited to the first 55 lines); for *directories*, it will show a _directory_ _listing_. By looking at the preview, you should hopefully be able to decide whether you want to _keep_ the file or _junk_ it.
101
+
102
+ == <tt>svn revisions</tt> (revisions browser)
103
+
104
+ Lets you interactively step through all revisions of a file/directory/repository.
105
+
106
+ Screenshot:
107
+ link:include/svn_revisions.png
108
+
109
+ Use the <tt>--forwards</tt> flag if you want to <i>start at the oldest revision</i> and step forwards through time rather than starting at the latest revision and stepping backwards (the default).
110
+
111
+
112
+ == <tt>svn status</tt>
76
113
 
77
114
  _Without_ this gem installed (really long):
78
115
 
@@ -112,32 +149,6 @@ _Without_ this gem installed (really long):
112
149
  A gemables/subversion/bin/svn
113
150
  M applications/underlord/vendor/plugins/rails_smith/tasks/shared/base.rake
114
151
 
115
- == <tt>svn each_unadded</tt>
116
-
117
- My personal favorite. This command is useful for keeping your working copies clean -- getting rid of all those accumulated temp files (or *ignoring* or *adding* them if they're something that _all_ users of this repository should be aware of).
118
-
119
- It simply goes through each "unadded" file (each file reporting a status of <tt>?</tt>) reported by <tt>svn status</tt> and asks you what you want to do with them -- *add*, *delete*, or *ignore*.
120
-
121
- > svn each_unadded
122
-
123
- What do you want to do with plugins/database_log4r/doc?
124
- (shows preview)
125
- (a)dd, (d)elete, add to svn:(i)ignore property, or [Enter] to do nothing > i
126
- Ignoring...
127
-
128
- What do you want to do with applications/underlord/db/schema.rb?
129
- (shows preview)
130
- (a)dd, (d)elete, add to svn:(i)ignore property, or [Enter] to do nothing > a
131
- Adding...
132
-
133
- What do you want to do with applications/underlord/vendor/plugins/exception_notification?
134
- (shows preview)
135
- (a)dd, (d)elete, add to svn:(i)ignore property, or [Enter] to do nothing > d
136
- Are you pretty much *SURE* you want to 'rm -rf applications/underlord/vendor/plugins/exception_notification'? (y)es, (n)o > y
137
- Deleting...
138
-
139
- For *files*, it will show a preview of the _contents_ of that file (limited to the first 55 lines); for *directories*, it will show a _directory_ _listing_. By looking at the preview, you should hopefully be able to decide whether you want to _keep_ the file or _junk_ it.
140
-
141
152
  ==<tt>svn externalize</tt> / <tt>externals</tt> / <tt>edit_externals</tt>
142
153
 
143
154
  Shortcut for creating an svn:external...
@@ -202,17 +213,6 @@ You can now do commands like this:
202
213
 
203
214
  (The _standard_ +svn+ command only accepts a _single_ source and a _single_ destination!)
204
215
 
205
- == <tt>svn revisions</tt> (revisions browser)
206
-
207
- Lets you interactively step through all revisions of a file/directory/repository.
208
-
209
-
210
- Note: You may have to svn update your working copy in order for svn log (and hence svn revisions) to be able to see the revisions you just committed.
211
-
212
-
213
- Use the <tt>--forwards</tt> flag if you want to <u>start at the oldest revision</u> and step forwards through time rather than starting at the latest revision and stepping backwards (the default).
214
-
215
-
216
216
  == <tt>svn commit</tt>
217
217
 
218
218
  === --skip-notification / --covert
@@ -277,7 +277,7 @@ You can, of course, get a lits of the custom commands that have been added by us
277
277
  * --print-commands (prints out the /usr/bin/svn commands before executing them)
278
278
  * --debug (sets $debug = true)
279
279
 
280
- ==<tt>colordiff</tt>
280
+ ==Requirement: <tt>colordiff</tt>
281
281
 
282
282
  +colordiff+ is used to colorize <tt>svn diff</tt> commands (+ lines are blue; - lines are red)
283
283
 
@@ -292,6 +292,23 @@ Suggestion: change the colors in <tt>/etc/colordiffrc</tt> to be more readable:
292
292
  diffstuff=cyan
293
293
  cvsstuff=magenta
294
294
 
295
+ ==A workaround for the <tt>Commit failed; Your file or directory 'some file' is probably out-of-date</tt> problem==
296
+
297
+ svn: Commit failed (details follow):
298
+ svn: Your file or directory 'some file' is probably out-of-date
299
+ svn: The version resource does not correspond to the resource within the transaction. Either the requested version resource is out of date (needs to be updated), or the requested version resource is newer than the transaction root (restart the commit).
300
+ Sending some file
301
+ (Doesn't actually finish the commit)
302
+
303
+ I'm still not sure what causes it (I didn't think I was doing anything _that_ out of the ordinary...) or how to _prevent_ it, because it keep happening to me (maybe I'm the only one?)... but I've at least automated the "fix" for this state somewhat.
304
+
305
+ The only way I've found to resolve this problem is to delete the entire directory and restore it (with svn update).
306
+
307
+ It must have something to do with something in the .svn directories not matching up the way that svn expects.
308
+
309
+ Anyway, the <tt>svn fix_out_of_date_commit_state</tt> command attempts to automate most of that process for you.
310
+
311
+
295
312
  ==Bash command completion
296
313
 
297
314
  If you want command completion for the svn subcommands (and I don't blame you if you don't -- the default command completion is <i>much faster</i> and already gives you completion for filenames!), just add this line to your <tt>~/.bashrc</tt> :
@@ -351,27 +368,14 @@ But... as with most things written in Ruby, it's all more about *productivity* t
351
368
 
352
369
  Take the best ideas from these and incorporate:
353
370
  * /usr/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/scm/subversion.rb
354
- * /usr/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/scm/subversion_log_parser.rb
355
371
  * /usr/lib/ruby/gems/1.8/gems/lazysvn-0.1.3/lib/subversion.rb
356
372
 
357
373
  Possibly switch to LazySvn.
358
374
 
359
375
  After you save/edit/set an svn:externals, it should try to automatically pretty up the margins/alignment for you.
360
376
 
361
- Color menu_item for do you want to edit this external yes/no
362
-
363
- ====================================================================================================
364
- Diff of externals (**don't forget to commit these too!**):
365
- ----------------------------------------------------------------------------------------------------
366
- to use ANSI underlines/colors
367
-
368
377
  Done, I think:
369
378
  Make sure to show errors!
370
- ~/svn st * wasn't showing an error it should have been
371
- > /usr/bin/svn status change_all_externals.rb change_all_externals.sh devscripts frontend glass glass.net potluck shared
372
- svn: 'change_all_externals.rb' is not a working copy
373
-
374
- If wrapped svn ever exits with an error code (such as 1), we ought to throw a fit as well
375
379
 
376
380
  If there is an error during an update, such as this one:
377
381
  Fetching external item into 'glass/rails_backend/vendor/plugins/our_extensions'
@@ -10,6 +10,7 @@ gem 'facets', '>=1.8.51'
10
10
  require 'facets/core/kernel/require_local'
11
11
  require 'facets/core/enumerable/uniq_by'
12
12
  require 'facets/core/kernel/silence_stream'
13
+ require 'facets/core/module/initializer'
13
14
 
14
15
  gem 'qualitysmith_extensions', '>=0.0.7'
15
16
 
@@ -20,6 +21,7 @@ gem 'qualitysmith_extensions', '>=0.0.7'
20
21
  #require 'facets/core/class/cattr'
21
22
  gem 'qualitysmith_extensions'
22
23
  require 'qualitysmith_extensions/module/attribute_accessors'
24
+ require 'qualitysmith_extensions/module/guard_method'
23
25
 
24
26
  # RSCM is used for some of the abstraction, such as for parsing log messages into nice data structures. It seems like overkill, though, to use RSCM for most things...
25
27
  gem 'rscm'
@@ -32,6 +34,7 @@ module Subversion
32
34
  # True if you want output from svn to be colorized (useful if output is for human eyes, but not useful if using the output programatically)
33
35
  @@color = false
34
36
  mattr_accessor :color
37
+ mguard_method :with_color!, :@@color
35
38
 
36
39
  # If true, will only output which command _would_ have been executed but will not actually execute it.
37
40
  @@dry_run = false
@@ -78,6 +81,10 @@ module Subversion
78
81
  add_to_property 'externals', options[:local_path], "#{options[:as]} #{repo_url}"
79
82
  end
80
83
 
84
+ def self.export(path_or_url, target)
85
+ execute "export #{path_or_url} #{target}"
86
+ end
87
+
81
88
  # Removes the given items from the repository and the disk. Items may contain wildcards.
82
89
  def self.remove(*args)
83
90
  execute "rm #{args.join ' '}"
@@ -143,6 +150,11 @@ module Subversion
143
150
  execute("update #{args.join ' '}")
144
151
  end
145
152
 
153
+ def self.commit(*args)
154
+ args = ['./'] if args.empty?
155
+ execute("commit #{args.join ' '}")
156
+ end
157
+
146
158
  # The output from `svn status` is nicely divided into two "sections": the section which pertains to the current working copy (not
147
159
  # counting externals as part of the working copy) and then the section with status of all of the externals.
148
160
  # This method returns the first section.
@@ -180,11 +192,19 @@ module Subversion
180
192
  }
181
193
  end
182
194
 
183
- # Returns the local modifications to the working directory specified by +path+.
195
+ # Returns the modifications to the working directory or URL specified in +args+.
184
196
  def self.diff(*args)
185
197
  args = ['./'] if args.empty?
186
- #puts("diff #{"--diff-cmd colordiff" if color} #{args.join ' '}")
187
- execute("diff #{"--diff-cmd colordiff" if color} #{args.join ' '}")
198
+ execute("diff #{"--diff-cmd colordiff" if color?} #{args.join ' '}")
199
+ end
200
+ # Parses the output from diff and returns an array of Diff objects.
201
+ def self.diffs(*args)
202
+ args = ['./'] if args.empty?
203
+ raw_diffs = nil
204
+ with_color! false do
205
+ raw_diffs = diff(*args)
206
+ end
207
+ DiffsParser.new(raw_diffs).parse
188
208
  end
189
209
 
190
210
  # It's easy to get/set properties, but less easy to add to a property. This method uses get/set to simulate add.
@@ -264,9 +284,16 @@ module Subversion
264
284
  # Returns the revision number for head.
265
285
  def self.latest_revision(*args)
266
286
  args = ['./'] if args.empty?
287
+ # The revision returned by svn status -u seems to be a pretty reliable way to get this. Does anyone know of a better way?
267
288
  matches = /Status against revision:\s+(\d+)/m.match(status_against_server(args))
268
289
  matches && matches[1]
269
290
  end
291
+ # Returns the revision number for the working directory(/file?) specified by +path+
292
+ def self.latest_revision_for_path(path)
293
+ # The revision returned by svn info seems to be a pretty reliable way to get this. Does anyone know of a better way?
294
+ matches = info(path).match(/^Revision: (\d+)/)
295
+ matches && matches[1]
296
+ end
270
297
 
271
298
  # Returns an array of RSCM::Revision objects
272
299
  def self.revisions(*args)
@@ -287,10 +314,15 @@ module Subversion
287
314
  execute "info #{args.join(' ')}"
288
315
  end
289
316
 
317
+ def self.url(path_or_url = './')
318
+ matches = info(path_or_url).match(/^URL: (.+)/)
319
+ matches && matches[1]
320
+ end
321
+
290
322
  # :todo: needs some serious unit-testing love
291
323
  def self.base_url(path_or_url = './')
292
- matches = info(path_or_url).match(/^Repository Root: (.+)/)
293
- matches && matches[1]
324
+ matches = info(path_or_url).match(/^Repository Root: (.+)/)
325
+ matches && matches[1]
294
326
 
295
327
  # It appears that we might need to use this old way (which looks at 'URL'), since there is actually a
296
328
  # base_url = nil # needed so that base_url variable isn't local to loop block (and reset during next iteration)!
@@ -407,10 +439,8 @@ end
407
439
 
408
440
 
409
441
 
410
- #Subversion.const_set(:RevisionProperty) = Struct.new(:name, :repository_path)
411
-
442
+ #-----------------------------------------------------------------------------------------------------------------------------
412
443
  module Subversion
413
-
414
444
  RevisionProperty = Struct.new(:name, :value)
415
445
 
416
446
  # Represents an "externals container", which is a directory that has the <tt>svn:externals</tt> property set to something useful.
@@ -458,6 +488,62 @@ module Subversion
458
488
  self.container_dir == other.container_dir
459
489
  end
460
490
  end
461
- end
462
491
 
492
+ # A collection of Diff objects in in file_name => diff format.
493
+ class Diffs < Hash
494
+ end
495
+
496
+ class Diff
497
+ attr_reader :filename, :diff
498
+ initializer :filename do
499
+ @diff = ''
500
+ end
501
+ def filename_pretty
502
+ filename.ljust(100).black_on_white
503
+ end
504
+ end
505
+
506
+ class DiffsParser
507
+ class ParseError < Exception; end
508
+ initializer :raw_diffs
509
+ @state = nil
510
+ def parse
511
+ diffs = Diffs.new
512
+ current_diff = nil
513
+ @raw_diffs.each_line do |line|
514
+ if line =~ /^Index: (.*)$/
515
+ current_diff = Diff.new($1)
516
+ diffs[current_diff.filename] = current_diff #unless current_diff.nil?
517
+ @state = :immediately_after_filename
518
+ next
519
+ end
520
+
521
+ if current_diff.nil?
522
+ raise ParseError.new("The raw diff input didn't begin with 'Index:'!")
523
+ end
524
+
525
+ if @state == :immediately_after_filename
526
+ if line =~ /^===================================================================$/ ||
527
+ line =~ /^---.*\(revision \d+\)$/ ||
528
+ line =~ /^\+\+\+.*\(revision \d+\)$/ ||
529
+ line =~ /^@@ .* @@$/
530
+ # Skip
531
+ next
532
+ else
533
+ @state= :inside_the_actual_diff
534
+ end
535
+ end
536
+
537
+ if @state == :inside_the_actual_diff
538
+ current_diff.diff << line
539
+ else
540
+ raise ParseError.new("Expected to be in :inside_the_actual_diff state, but was not.")
541
+ end
542
+ end
543
+ diffs.freeze
544
+ diffs
545
+ end
546
+ end
547
+
548
+ end
463
549
  end
@@ -52,7 +52,7 @@ class String
52
52
  end
53
53
  def colorize_svn_diff
54
54
  if Subversion.color
55
- self.gsub(/^(Index: )(.*)$/) { $2.underline}.
55
+ self.gsub(/^(Index: )(.*)$/) { $2.ljust(100).black_on_white}.
56
56
  gsub(/^=+\n/, '')
57
57
  else
58
58
  self
@@ -8,6 +8,8 @@ require 'facets/core/array/select' # select!
8
8
  require 'facets/core/kernel/with' # returning
9
9
  require 'facets/core/string/lines'
10
10
  require 'facets/core/string/index_all'
11
+ require 'facets/core/string/to_re'
12
+ require 'facets/core/string/to_rx'
11
13
 
12
14
  gem 'qualitysmith_extensions', '>=0.0.3'
13
15
  require 'qualitysmith_extensions/enumerable/enum'
@@ -61,6 +63,19 @@ class String
61
63
  def relativize_path
62
64
  self.gsub(File.expand_path(FileUtils.getwd) + '/', '') # Simplify the directory by removing the working directory from it, if possible
63
65
  end
66
+ def highlight_occurences(search_pattern, color = :red)
67
+ self.gsub(search_pattern) { $&.send(color).bold }
68
+ end
69
+ end
70
+ def confirm(question, options = ['Yes', 'No'])
71
+ print question + " " +
72
+ "Yes".menu_item(:red) + ", " +
73
+ "No".menu_item(:green) +
74
+ " > "
75
+ response = ''
76
+ # Currently allow user to press Enter to accept the default.
77
+ response = $stdin.getc.chr.downcase while !['y', 'n', "\n"].include?(begin response.downcase!; response end)
78
+ response
64
79
  end
65
80
 
66
81
  Subversion.extend(Subversion::Extensions)
@@ -234,19 +249,24 @@ module Subversion
234
249
  alias_method :__knowingly_committing_broken_code, :__broken
235
250
  end
236
251
  def commit(*args)
252
+ latest_rev_before_commit = Subversion.latest_revision if @broken || @skip_notification
253
+
237
254
  Subversion.print_commands_for do
238
- puts svn(:capture, "propset svn:skip_commit_notification_for_next_commit true --revprop -r #{Subversion.latest_revision}", :prepare_args => false)
255
+ puts svn(:capture, "propset svn:skip_commit_notification_for_next_commit true --revprop -r #{latest_rev_before_commit}", :prepare_args => false)
239
256
  end if @skip_notification
240
257
  # :todo:
241
258
  # Add some logic to automatically skip the commit e-mail if the size of the files to be committed exceeds a threshold of __ MB.
242
259
  # (Performance idea: Only check the size of the files if svn st includes (bin)?)
243
260
 
244
- puts output = svn(:capture, 'commit', *(['--force-log'] + args))
261
+ svn(:system, 'commit', *(['--force-log'] + args))
245
262
 
246
- just_committed = (matches = output.match(/Committed revision (\d+)\./)) && matches[1]
263
+ # The following only works if we do :capture (`svn`), but that doesn't work so well (at all) if svn tries to open up an editor (vim),
264
+ # which is what happens if you don't specify a message.:
265
+ # puts output = svn(:capture, 'commit', *(['--force-log'] + args))
266
+ # just_committed = (matches = output.match(/Committed revision (\d+)\./)) && matches[1]
247
267
 
248
268
  Subversion.print_commands_for do
249
- puts svn(:capture, "propset code:broken true --revprop -r #{just_committed}", :prepare_args => false)
269
+ puts svn(:capture, "propset code:broken true --revprop -r #{latest_rev_before_commit + 1}", :prepare_args => false)
250
270
  end if @broken
251
271
 
252
272
  end
@@ -255,6 +275,50 @@ module Subversion
255
275
  # * look for .svn-commit files within current tree and if one is found, show what's in it and ask
256
276
  # "Found a commit message from a previous failed commit. {preview} Do you want to (u)se this message for the current commit, or (d)elete it?"
257
277
 
278
+ # A fix for this annoying problem that I seem to come across all too frequentrly:
279
+ # svn: Commit failed (details follow):
280
+ # svn: Your file or directory 'whatever.rb' is probably out-of-date
281
+ def fix_out_of_date_commit_state(dir)
282
+ dir = $1 if dir =~ %r|^(.*)/$| # Strip trailing slash.
283
+
284
+ puts Subversion.export("#{dir}", "#{dir}.new"). # Exports (copies) the contents of working copy 'dir' (including your uncommitted changes, don't worry! ... and you'll get a chance to confirm before anything is deleted; but sometimes although it exports files that are scheduled for addition, they are no longer scheduled for addition in the new working copy, so you have to re-add them) to non-working-copy 'dir.new'
285
+ add_exit_code_error
286
+ return if !$?.success?
287
+
288
+ system("mv #{dir} #{dir}.backup") # Just in case something goes ary
289
+ puts ''.add_exit_code_error
290
+ return if !$?.success?
291
+
292
+ puts "Restoring #{dir}..."
293
+ Subversion.update dir # Restore the directory to a pristine state so we will no longer get that annoying error
294
+
295
+ # Assure the user that dir.new really does have your latest changes
296
+ #puts "Here's a diff. Your changes/additions will be in the *right* (>) file."
297
+ #system("diff #{dir}.backup #{dir}")
298
+
299
+ # Merge those latest changes back into the pristine working copy
300
+ system("cp -R #{dir}.new/. #{dir}/")
301
+
302
+ # Assure the user one more time
303
+ puts Extensions.diff(dir)
304
+
305
+ # Actually commit
306
+ puts
307
+ response = confirm("Are you ready to try the commit again now?")
308
+ puts
309
+ if response == 'y'
310
+ puts "Great. Go for it."
311
+ #Subversion.commit dir
312
+ end
313
+
314
+ # Clean up
315
+ #puts
316
+ #response = confirm("Do you want to delete array.backup array.new now?")
317
+ puts "Don't forget to delete array.backup array.new now!"
318
+ #rm_rf array.backup, array.new
319
+ puts
320
+ end
321
+
258
322
  #-----------------------------------------------------------------------------------------------------------------------------
259
323
  module Diff
260
324
  Console::Command.pass_through({
@@ -287,7 +351,7 @@ module Subversion
287
351
  unless diff_output == ""
288
352
  #output.puts '-'*100
289
353
  #output.puts item.ljust(100, ' ').black_on_white.bold.underline
290
- output.puts item.black_on_white.bold
354
+ output.puts item.ljust(100).black_on_white.bold
291
355
  output.puts diff_output
292
356
  end
293
357
  end
@@ -449,6 +513,11 @@ End
449
513
  # Custom subcommands
450
514
  #-----------------------------------------------------------------------------------------------------------------------------
451
515
 
516
+ #-----------------------------------------------------------------------------------------------------------------------------
517
+ def url(*args)
518
+ puts Subversion.url(*args)
519
+ end
520
+
452
521
  #-----------------------------------------------------------------------------------------------------------------------------
453
522
  def repository_root(*args)
454
523
  puts Subversion.repository_root(*args)
@@ -574,15 +643,12 @@ End
574
643
 
575
644
  response = ""
576
645
  if File.directory?(file)
577
- print "Are you pretty much " + "SURE".bold + " you want to '" + "rm -rf #{file}".red.bold + "'? " +
578
- "Yes".menu_item(:red) + ", " +
579
- "No".menu_item(:green) +
580
- " > "
581
- response = $stdin.getc.chr.downcase while !['y', 'n', "\n"].include?(begin response.downcase!; response end)
646
+ response = confirm("Are you pretty much " + "SURE".bold + " you want to '" + "rm -rf #{file}".red.bold + "'? ")
582
647
  else
583
648
  response = "y"
584
649
  end
585
650
 
651
+ puts "response=#{response}"
586
652
  if response == 'y'
587
653
  print "\nDeleting... "
588
654
  FileUtils.rm_rf file
@@ -697,9 +763,7 @@ End
697
763
  command = "#{Subversion.executable} propedit svn:externals #{external.container_dir}"
698
764
  #puts command
699
765
  begin
700
- #print "Press Ctrl-C to skip, any other key to continue. (This will start up your default editor.) "
701
- print "Do you want to edit svn:externals for this directory?".black_on_white + ' ' + 'yes'.menu_item(:white) + '/' + 'No'.menu_item(:white) + " > "
702
- response = $stdin.getc.chr.downcase
766
+ response = confirm("Do you want to edit svn:externals for this directory?".black_on_white)
703
767
  system command if response == 'y'
704
768
  rescue Interrupt
705
769
  puts "\nGoodbye!"
@@ -816,12 +880,7 @@ End
816
880
  # we can use the empty string as a way to trigger a propdel...
817
881
  if value == ''
818
882
  puts
819
- print "Are you sure you want to delete property #{property_name}".red.bold + "'? " +
820
- "Yes".menu_item(:red) + ", " +
821
- "No".menu_item(:green) +
822
- " > "
823
- response = ''
824
- response = $stdin.getc.chr.downcase while !['y', 'n', "\n"].include?(begin response.downcase!; response end)
883
+ response = confirm("Are you sure you want to delete property #{property_name}".red.bold + "'? ")
825
884
  puts
826
885
  if response == 'y'
827
886
  Subversion.print_commands_for do
@@ -880,14 +939,32 @@ End
880
939
  # Only show revisions that are in need of a code review
881
940
  # :todo:
882
941
  def __unreviewed_only
883
- @unreviewed_only
942
+ @unreviewed_only = true
943
+ end
944
+
945
+ # Only show revisions that were committed by a certain author.
946
+ # :todo:
947
+ def __by(author)
948
+ @author_filter = author
949
+ end
950
+ def __author(author)
951
+ @author_filter = author
884
952
  end
885
953
  end
886
- # :todo: document in readme! test! release! annouce!
887
954
  def revisions(directory = './')
888
955
  puts "Getting list of revisions for '#{directory.white.bold}' ..."
889
956
 
890
957
  head = Subversion.latest_revision
958
+ revision_of_directory = Subversion.latest_revision_for_path(directory)
959
+
960
+ # It's possible for a working copy to get "out of date" (even if you were the last committer!), in which case svn log will
961
+ # only list revisions up to that revision (actually looks like it only goes up to and including Last Changed Rev: 2838,
962
+ # not Revision: 2839, as reported by svn info...)
963
+ if revision_of_directory < head
964
+ puts "The working copy '#{directory.white.bold}' appears to be out-of-date (#{revision_of_directory}) with respect to the head revision (#{head}). Updating..."
965
+ Subversion.update(directory)
966
+ end
967
+
891
968
  revisions = Subversion.revisions(directory)
892
969
 
893
970
  puts "#{revisions.length.to_s.bold} revisions found. Starting with #{@reverse ? 'oldest' : 'most recent'} revision and #{@reverse ? 'going forward in time' : 'going backward in time'}..."
@@ -969,12 +1046,32 @@ End
969
1046
  SvnCommand.execute("diff #{directory} --ignore-externals -r #{revs_to_compare.min}:#{revs_to_compare.max}")
970
1047
 
971
1048
  when 'g' # Grep the changeset
1049
+ # :todo; make it accept regexpes like /like.*this/im so you can make it case insensitive or multi-line
972
1050
  revs_to_compare = [other_rev, rev]
973
1051
  puts
1052
+ print 'Grep for'.bold + ' (Regular expressions ' + 'like.*this'.bold.blue + ' are allowed, but not ' + '/like.*this/im'.bold.blue + '): '
1053
+ search_pattern = $stdin.gets.chomp.to_rx
974
1054
  puts((' '*100).green.underline)
975
- print "Diffing #{revs_to_compare.min}:#{revs_to_compare.max}... ".bold
976
- puts
977
- puts Extensions.diff(directory, '-r', "#{revs_to_compare.min}:#{revs_to_compare.max}")
1055
+ puts "Searching `svn diff #{revs_to_compare.min}:#{revs_to_compare.max}` for #{search_pattern.to_s}... ".bold
1056
+ diffs = Subversion.diffs(directory, '-r', "#{revs_to_compare.min}:#{revs_to_compare.max}")
1057
+
1058
+ hits = 0
1059
+ diffs.each do |filename, diff|
1060
+ #.grep(search_pattern)
1061
+ if diff.diff =~ search_pattern
1062
+ puts diff.filename_pretty
1063
+ puts( diff.diff.grep(search_pattern). # This will get us just the interesting *lines* (as an array).
1064
+ map { |line| # Now, for each line...
1065
+ hits += 1
1066
+ line.highlight_occurences(search_pattern)
1067
+ }
1068
+ )
1069
+ end
1070
+ end
1071
+ if hits == 0
1072
+ puts "Search term not found!".red.bold
1073
+ end
1074
+ show_revision_again = false
978
1075
 
979
1076
  when 'l' # List revision properties
980
1077
  puts
@@ -997,6 +1094,14 @@ End
997
1094
 
998
1095
  show_revision_again = false
999
1096
 
1097
+ when 'c' # Cat all files from revision
1098
+ puts 'Not implemented yet'
1099
+ show_revision_again = false
1100
+
1101
+ when 'a' # Grep the cat
1102
+ puts 'Not implemented yet'
1103
+ show_revision_again = false
1104
+
1000
1105
  when 'r' # Mark as reviewed
1001
1106
  puts
1002
1107
  your_name = ENV['USER'] # I would use the same username that Subversion itself would use if you committed
@@ -75,69 +75,56 @@ class SubversionTest < Test::Unit::TestCase
75
75
  FileUtils.rm_r tmpdir
76
76
  end
77
77
  end
78
+ end
78
79
 
79
- def test_revert
80
- Subversion.revert 'foo', 'bar', 'hello/world'
81
- assert_equal 'svn revert foo bar hello/world', Subversion.executed.first
82
- end
83
-
84
- def test_executable
85
- Subversion.make_executable 'foo', 'bar', 'hello/world'
86
- assert_equal "svn propset svn:executable '' foo", Subversion.executed[0]
87
- assert_equal "svn propset svn:executable '' bar", Subversion.executed[1]
88
- assert_equal "svn propset svn:executable '' hello/world", Subversion.executed[2]
89
-
90
- Subversion.make_not_executable 'foo'
91
- assert_equal "svn propdel svn:executable foo", Subversion.executed[3]
92
- end
93
-
94
- def test_status
95
- Subversion.status 'foo'
96
- assert_equal "svn status foo", Subversion.executed.first
80
+ class DiffsParserTest < Test::Unit::TestCase
81
+ # def test_diff_class_acts_like_hash
82
+ # diff = Subversion::Diff['file.rb' => "some differences"]
83
+ # assert_equal 'some differences', diff['file.rb']
84
+ # end
85
+ def test_parser_error
86
+ assert_raise(Subversion::DiffsParser::ParseError) { Subversion::DiffsParser.new('what').parse }
97
87
  end
98
-
99
- def test_revisions
100
- Subversion.stubs(:log).returns(<<End)
101
- ------------------------------------------------------------------------
102
- r407119 | moo | 2006-05-16 20:27:28 -0500 (Tue, 16 May 2006) | 5 lines
103
- Changed paths:
104
- M /trunk/cow/black.rb
105
- M /trunk/cow/brown.rb
106
-
107
- Commit message...
108
- ------------------------------------------------------------------------
88
+ def test_parser
89
+ diffs = Subversion::DiffsParser.new(<<End).parse
90
+ Index: lib/test_extensions.rb
91
+ ===================================================================
92
+ --- lib/test_extensions.rb (revision 2871)
93
+ +++ lib/test_extensions.rb (revision 2872)
94
+ @@ -6,6 +6,7 @@
95
+ require_local 'some_file'
96
+
97
+ gem 'qualitysmith_extensions'
98
+ +require 'qualitysmith_extensions/regexp/join'
99
+ require 'qualitysmith_extensions/kernel/capture_output.rb'
100
+ require 'qualitysmith_extensions/kernel/simulate_input.rb'
101
+
102
+ Index: Readme
103
+ ===================================================================
104
+ --- Readme (revision 0)
105
+ +++ Readme (revision 2872)
106
+ @@ -0,0 +1,2 @@
107
+ +* Blah blah blah
108
+ +* Blah blah blah
109
109
  End
110
- assert_equal 1, Subversion.revisions.length
111
- assert_equal RSCM::Revision, Subversion.revisions[0].class
112
- assert_equal RSCM::RevisionFile, Subversion.revisions[0][0].class
113
- assert_equal 'modified', Subversion.revisions[0][0].status.downcase
114
- assert_equal 'trunk/cow/black.rb', Subversion.revisions[0][0].path
115
- assert_equal 'trunk/cow/brown.rb', Subversion.revisions[0][1].path
116
- assert_equal 'Commit message...', Subversion.revisions[0].message
117
- end
110
+ assert_equal Subversion::Diffs, diffs.class
111
+ assert diffs.frozen?
112
+ assert_equal 2, diffs.keys.size
113
+ assert_equal 2, diffs.values.size
114
+ assert_equal <<End, diffs['lib/test_extensions.rb'].diff
115
+ require_local 'some_file'
116
+
117
+ gem 'qualitysmith_extensions'
118
+ +require 'qualitysmith_extensions/regexp/join'
119
+ require 'qualitysmith_extensions/kernel/capture_output.rb'
120
+ require 'qualitysmith_extensions/kernel/simulate_input.rb'
118
121
 
119
- def test_revision_properties_names
120
- Subversion.stubs(:proplist).returns(<<End)
121
- Unversioned properties on revision 2819:
122
- svn:log
123
- svn:author
124
- svn:date
125
122
  End
126
- assert_equal ['svn:log', 'svn:author', 'svn:date'], Subversion.revision_properties_names(rev = 14)
127
- end
128
- def test_revision_properties
129
- Subversion.stubs(:proplist).returns(<<End)
130
- Unversioned properties on revision 2819:
131
- svn:log
132
- svn:author
133
- svn:date
123
+ assert_equal <<End, diffs['Readme'].diff
124
+ +* Blah blah blah
125
+ +* Blah blah blah
134
126
  End
135
- Subversion.stubs(:get_revision_property).returns('a value')
136
127
 
137
- assert_equal [
138
- Subversion::RevisionProperty.new('svn:log', 'a value'),
139
- Subversion::RevisionProperty.new('svn:author', 'a value'),
140
- Subversion::RevisionProperty.new('svn:date', 'a value'),
141
- ], Subversion.revision_properties(rev = 14)
142
128
  end
129
+
143
130
  end
@@ -3,64 +3,15 @@ require File.dirname(__FILE__) + '/test_helper'
3
3
  require_local '../lib/svn-command/svn_command.rb'
4
4
  require 'facets/core/string/to_re'
5
5
  require 'yaml'
6
-
7
-
8
6
  require 'facets/core/module/alias_method_chain'
9
- require 'qualitysmith_extensions/string/each_char_with_index'
10
- module Test
11
- module Unit
12
- module Assertions
13
- # Rather than showing the expected and the actual and asking the user to figure out the commonalities and differences
14
- # himself, this method will highlight the differences for the user (in color), so that they can be spotted in less than
15
- # an instant!
16
- # Strings: show common characters in a plain color and highlight the characters that differ (at that index) in yellow.
17
- # Strings: show common elements in a plain color and highlight the elements that differ (at that index) in yellow.
18
- def assert_equal_with_difference_highlighting(expected, actual, message=nil)
19
- String.class_eval do
20
- alias_method :colorize, :colorize_without_no_color
21
- end
22
- if String===expected && String===actual
23
- expected_with_highlighting = ''
24
- actual_with_highlighting = ''
25
- expected.each_char_with_index do |i, c|
26
- if c != actual[i].chr
27
- expected_with_highlighting << c.yellow
28
- actual_with_highlighting << actual[i].chr.yellow
29
- else
30
- expected_with_highlighting << c
31
- actual_with_highlighting << c
32
- end
33
-
34
- end
35
- full_message = build_message(message, <<End, expected_with_highlighting, actual_with_highlighting)
36
- <?>
37
- expected but was
38
- <?>.
39
- End
40
- puts actual_with_highlighting if expected != actual
41
- assert_block(full_message) { expected == actual }
42
- else
43
- assert_equal_without_difference_highlighting(expected, actual, message)
44
- end
45
- String.class_eval do
46
- alias_method :colorize, :colorize_with_no_color
47
- end
48
- end # def assert_equal_with_difference_highlighting
7
+ require 'qualitysmith_extensions/colored/toggleability'
8
+ require 'qualitysmith_extensions/regexp/join'
49
9
 
50
- alias_method_chain :assert_equal, :difference_highlighting
51
- end
52
- end
53
- end
54
10
 
55
11
 
56
- Subversion.color = false
57
12
  # Makes testing simpler. We can test all the *colorization* features via *manual* testing (since they're not as critical).
58
- class String
59
- def colorize_with_no_color(string, options = {})
60
- string
61
- end
62
- alias_method_chain :colorize, :no_color
63
- end
13
+ Subversion.color = false
14
+ String.color_on! false
64
15
 
65
16
  module Subversion
66
17
  class BaseSvnCommandTest < Test::Unit::TestCase
@@ -147,11 +98,11 @@ end
147
98
  class SvnCommitTest < BaseSvnCommandTest
148
99
  def test_1
149
100
  SvnCommand.execute("commit -m 'just an ordinary commit message!'")
150
- assert_equal "svn commit -m 'just an ordinary commit message!' --force-log", Subversion.executed.join
101
+ assert_equal ["svn commit -m 'just an ordinary commit message!' --force-log"], Subversion.executed
151
102
  end
152
103
  def test_lots_of_options
153
104
  SvnCommand.execute("commit --non-recursive -q -m '' --targets some_file ")
154
- assert_equal "svn commit --non-recursive -q -m '' --targets some_file --force-log", Subversion.executed.join
105
+ assert_equal ["svn commit --non-recursive -q -m '' --targets some_file --force-log"], Subversion.executed
155
106
  end
156
107
  def test_that_complex_quoting_doesnt_confuse_it
157
108
  original_message = "Can't decide how many \"'quotes'\" to use!"
@@ -565,7 +516,7 @@ end
565
516
  # Changeset/commit/log Browser
566
517
 
567
518
  class SvnRevisionsTest < BaseSvnCommandTest
568
- def test_1
519
+ def set_up_stubs
569
520
  Subversion.stubs(:revisions).returns(
570
521
  begin
571
522
  RSCM::Revisions.class_eval do
@@ -600,8 +551,14 @@ class SvnRevisionsTest < BaseSvnCommandTest
600
551
  revisions.revisions = [revision1, revision2]
601
552
  end
602
553
  )
554
+ Subversion.stubs(:latest_revision).returns(42)
555
+ Subversion.stubs(:latest_revision_for_path).returns(42)
603
556
  Subversion.stubs(:diff).returns("the diff")
604
-
557
+ end
558
+
559
+ def test_view_changeset
560
+ set_up_stubs
561
+
605
562
  output = simulate_input(
606
563
  'v' + # View this changeset
607
564
  "\n" + # Continue to revision 1800
@@ -609,52 +566,51 @@ class SvnRevisionsTest < BaseSvnCommandTest
609
566
  ) do
610
567
  capture_output { SvnCommand.execute('revisions') }
611
568
  end
612
- puts output
613
- require 'unroller'
569
+ #puts output
570
+ #require 'unroller'
614
571
  #Unroller::trace :exclude_classes => /PP|PrettyPrint/ do
615
572
 
616
- assert_equal <<-End, output
617
- Getting list of revisions for './' ...
618
- 2 revisions found. Starting with most recent revision and going backward in time...
619
-
620
- 2. r1800 | tyler | 2007-12-01 00:00:00
573
+ assert_match Regexp.loose_join(
574
+ "Getting list of revisions for './' ...
575
+ 2 revisions found. Starting with most recent revision and going backward in time...",
576
+ # Show 1800 again
577
+ "2. r1800 | tyler | 2007-12-01 00:00:00
621
578
  I say! Quite the storm, what!
622
579
 
623
580
  A dir/file1
624
581
  M dir/file2
625
- View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files from revision, grep the cat,
626
- mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys >
627
-
628
-
629
-
630
-
631
-
632
-
633
-
634
-
635
-
636
-
637
- Diffing 1799:1800...
638
- the diff
639
-
640
- 2. r1800 | tyler | 2007-12-01 00:00:00
582
+ View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files from revision, grep the cat,
583
+ mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys >",
584
+ # Show the diff
585
+ "Diffing 1799:1800...",
586
+ "the diff",
587
+ # Show 1800 again
588
+ "2. r1800 | tyler | 2007-12-01 00:00:00
641
589
  I say! Quite the storm, what!
642
590
 
643
591
  A dir/file1
644
592
  M dir/file2
645
- View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files from revision, grep the cat,
646
- mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys > Next...
647
-
648
- 1. r1801 | tyler | 2007-12-02 00:00:00
593
+ View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files from revision, grep the cat,
594
+ mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys > Next...",
595
+ # Now show 1801
596
+ "1. r1801 | tyler | 2007-12-02 00:00:00
649
597
  These Romans are crazy!
650
598
 
651
599
  M dir/file2
652
- View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files from revision, grep the cat,
653
- mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys > Next...
654
- End
655
- #end
600
+ View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files from revision, grep the cat,
601
+ mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys > Next...",
602
+ :multi_line => true
603
+ ), output
604
+
605
+
606
+ =begin
607
+ /.*/
608
+ }.*
609
+ =end
610
+
611
+
656
612
  assert_equal [
657
- "svn status -u ./" # To find head
613
+ #"svn status -u ./" # To find head
658
614
  ], Subversion.executed
659
615
  end
660
616
  end
data/test/test_helper.rb CHANGED
@@ -4,12 +4,10 @@ require 'facets/core/kernel/require_local'
4
4
  require 'facets/core/kernel/load_local'
5
5
  require 'stubba'
6
6
  $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
7
- require_local "shared/test_helper"
8
7
 
9
- gem 'qualitysmith_extensions', '>=0.0.3'
10
- require 'qualitysmith_extensions/test/assert_exception.rb'
11
- require 'qualitysmith_extensions/kernel/capture_output.rb'
12
- require 'qualitysmith_extensions/kernel/simulate_input.rb'
8
+ gem 'test_extensions'
9
+ require 'test_extensions'
10
+ gem 'qualitysmith_extensions'
13
11
 
14
12
  require_local '../lib/svn-command/subversion'
15
13
  if $mock_subversion
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: svn-command
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.4
7
- date: 2007-04-26 00:00:00 -07:00
6
+ version: 0.2.5
7
+ date: 2007-05-01 00:00:00 -07:00
8
8
  summary: A nifty wrapper command for Subversion's command-line svn client
9
9
  require_paths:
10
10
  - lib
@@ -41,8 +41,6 @@ files:
41
41
  - test/subversion_extensions_test.rb
42
42
  - test/subversion_test.rb
43
43
  - test/svn_command_test.rb
44
- - test/shared/test_helper.rb
45
- - test/shared/test_helpers/test_colorizer.rb
46
44
  - bin/rscm_test
47
45
  - bin/command_completion_for_svn_command
48
46
  - bin/svn
@@ -1,5 +0,0 @@
1
- require 'test/unit'
2
- require 'rubygems'
3
- gem 'qualitysmith_extensions'
4
- require 'qualitysmith_extensions/test/all'
5
- require File.expand_path(File.dirname(__FILE__)+'/' + 'test_helpers/test_colorizer')
@@ -1,109 +0,0 @@
1
- require 'rubygems'
2
- gem 'colored'
3
- require 'test/unit'
4
- require 'colored'
5
-
6
- module Test::Unit
7
-
8
- class Error
9
- # the 'E' that is displayed as the tests are run
10
- def single_character_display
11
- "E".red.bold
12
- end
13
-
14
- # the long message that is displayed after test is run
15
- def long_display
16
- backtrace = filter_backtrace(@exception.backtrace).join("\n ")
17
- [
18
- "Error".red.bold,
19
- ":\n",
20
- "#@test_name:".white,
21
- "\n", "#{message}".red,
22
- "\n #{backtrace}".gsub(/:(\d+):/,":#{'\1'.red}:")
23
- ].join('')
24
- end
25
- end
26
-
27
-
28
- class Failure
29
- # the 'E' that is displayed as the tests are run
30
- def single_character_display
31
- "F".yellow.bold
32
- end
33
-
34
- # the long message that is displayed after test is run
35
- def long_display
36
- location_display = if(location.size == 1)
37
- location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
38
- else
39
- "\n [#{location.join("\n ")}]"
40
- end
41
- [
42
- "Failure".yellow.bold,
43
- ":\n","#@test_name".white,
44
- "#{location_display}".gsub(/:(\d+)/, ":#{'\1'.yellow}"),
45
- ":\n", "#@message".yellow
46
- ].join('')
47
- end
48
- end
49
-
50
- # it is necessary to do a class_eval for the TestRunner class
51
- # through the AutoRunner class, since the require in the AutoRunner
52
- # class will overwrite what we do here otherwise.
53
- #
54
- # We must do the same thing inside of the TestRunner class
55
- # class_eval for the TestResult class. We Modify the
56
- # TestRunnerMediator class after the require is called,
57
- # which will then modify the TestResult class.
58
- #
59
- # test_finished is the function that will output the
60
- # '.' period during the test runs
61
- #
62
- # the to_s for TestResult class returns the string
63
- # for the final tallied results
64
- class AutoRunner
65
- RUNNERS[:console] = proc do |r|
66
- require 'test/unit/ui/console/testrunner'
67
- Test::Unit::UI::Console::TestRunner.class_eval %q{
68
- def test_finished(name)
69
- output_single('.'.green, 1) unless (@already_outputted)
70
- nl(3)
71
- @already_outputted = false
72
- end
73
-
74
- def create_mediator(suite)
75
- require 'test/unit/ui/testrunnermediator'
76
- Test::Unit::UI::TestRunnerMediator.class_eval %q{
77
- def create_result
78
- Test::Unit::TestResult.class_eval %q{
79
- def to_s
80
- rc = [
81
- "#{run_count}".white.bold,
82
- "tests".white
83
- ].join(' ')
84
- ac = [
85
- "#{assertion_count}".white.bold,
86
- "assertions".white
87
- ].join(' ')
88
- fc = [
89
- "#{failure_count}".yellow.bold,
90
- "failures".yellow
91
- ].join(' ')
92
- ec = [
93
- "#{error_count}".red.bold,
94
- "errors".red
95
- ].join(' ')
96
- [rc, ac, fc, ec].join(', ')
97
- end
98
- }
99
- TestResult.new
100
- end
101
- }
102
- return Test::Unit::UI::TestRunnerMediator.new(suite)
103
- end
104
- }
105
- Test::Unit::UI::Console::TestRunner
106
- end
107
- end
108
-
109
- end