rake-dotnet 0.0.1 → 0.0.2

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/History.txt CHANGED
@@ -1,3 +1,48 @@
1
+ === 0.0.2 / 2009-03-21
2
+
3
+ * Several major enhancements
4
+
5
+ * Versioner
6
+ * Figure out a 4-token version number, major.minor.build.revision, taking:
7
+ * major.minor from version.template.txt
8
+ * build from ENV['BUILD_NUMBER'] (used by TeamCity)
9
+ * revision from svn working copy that the build is occurring in
10
+
11
+ * AssemblyInfoTask
12
+ * Create AssemblyInfo.cs file(s) based on supplied AssemblyInfo.template.cs file(s)
13
+ * Perform token replacement within AssemblyInfo.cs to watermark assemblies with:
14
+ * major.minor.build.revision version number (from RDNVERSION)
15
+ * Product Name (from PRODUCT_NAME)
16
+ * Company Name (from COMPANY_NAME)
17
+ * Build configuration (from CONFIGURATION)
18
+
19
+ * MsBuildTask
20
+ * Perform compilation of msbuild project files
21
+
22
+ * HarvestOutputTask
23
+ * Harvest output of projects to a directory to act as main dumping ground to then zip up for build-artifacts to enable CI-parallelisation later
24
+
25
+ * HarvestWebApplicationTask
26
+ * Harvest web-applications (greedily) to a directory
27
+
28
+ * XUnitTask
29
+ * Run xunit.net tests from assemblies with *Tests* in filename
30
+
31
+ * FxCopTask
32
+ * Run fxcop against assemblies whose filenames contain PRODUCT_NAME
33
+
34
+ * NCoverTask
35
+ * Run ncover.console against assemblies to generate coverage data
36
+ * Run ncover.reporting against coverage data to generate coverage reports
37
+ * Limited to simple case in this release
38
+
39
+ * RDNPackageTask
40
+ * Package a directory as a zip file, named like {name}-{configuration}-v{version}.zip
41
+ * Uses 7-zip, instead of rake's built-in PackageTask, which would have required taking a dependency on cygwin (7-zip is lighter)
42
+
43
+ * A demo solution as an example of usage
44
+ * See http://my-svn.assembla.com/svn/nrws/trunk/rake_dotnet/lib/Demo
45
+
1
46
  === 0.0.1 / 2009-03-09
2
47
 
3
48
  * 1 major enhancement
data/Manifest.txt CHANGED
@@ -2,6 +2,5 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
- bin/rake_dotnet
6
5
  lib/rake_dotnet.rb
7
6
  test/test_rake_dotnet.rb
data/README.txt CHANGED
@@ -20,6 +20,8 @@ Rake dotnet is a bunch of things that aim at doing the work of creating a featur
20
20
  * Build the project files to produce said DLLs (call msbuild against the project file(s))
21
21
  * Run XUnit.NET unit tests against said DLLs, and output reports (wrap xunit.console.exe)
22
22
  * Run FxCop against said DLLs, and output reports (wrap fxcopcmd.exe)
23
+ * Run NCover against build output to generate coverage metrics
24
+ * Run NCover against coverage to generate coverage reports
23
25
  * Harvest build output
24
26
  * Package build output as a zip file, naming it like {product-name}-{configuration}-v{version}.zip
25
27
 
@@ -28,12 +30,11 @@ Rake dotnet is a bunch of things that aim at doing the work of creating a featur
28
30
  (In no particular order)
29
31
  * rdoc documentation to supplement blog'd about
30
32
  * Support other test-runners - nunit, mbunit, gallio
31
- * Change harvest/package to take file-glob include/exclude parameters (as rake's PackageTask) - allow more flexible building of packages
32
33
  * Support code-coverage runner(s) - ncover 1.68, ncover 3, partcover
33
34
  * Support clone-detective...?
34
35
  * Support other source-controls to get build version number - git, mercurial, cvs(?), TFS
35
- * Support 7z compression for packaging to eliminate cygwin dependency (7zip is easier/cleaner to get & maintain)
36
36
  * Support changing the conventions to allow users to specify their own source structure
37
+ * Provide an InstallPad for the 3rdparty bits
37
38
 
38
39
  == REQUIREMENTS:
39
40
 
data/Rakefile CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
- require './lib/rake_dotnet.rb'
5
+ require 'Pathname'
6
+ require 'rake/clean'
6
7
 
7
- Hoe.new('rake-dotnet', Rake_dotnet::VERSION) do |p|
8
+ Hoe.new('rake-dotnet', '0.0.2') do |p|
8
9
  p.author = 'Peter Mounce'
9
10
  p.description = 'Making a .NET build-automation dev\'s life easier, one angle-bracket at a time'
10
11
  p.email = 'pete@neverrunwithscissors.com'
@@ -15,5 +16,25 @@ Hoe.new('rake-dotnet', Rake_dotnet::VERSION) do |p|
15
16
  p.extra_deps = ['rake']
16
17
  end
17
18
 
19
+ generated_library = File.join('lib','rake_dotnet.rb')
20
+ CLOBBER.include generated_library
21
+ file generated_library do |f|
22
+ text = ''
23
+ files = ['header.rb','defaults.rb','assemblyinfo.rb','fxcop.rb','harvester.rb','msbuild.rb','ncover.rb','package.rb','sevenzip.rb','svn.rb','version.rb','xunit.rb']
24
+ gl = File.open(generated_library, 'a')
25
+ files.each do |file|
26
+ text = File.read(File.join('lib', file))
27
+ gl.puts text
28
+ gl.puts
29
+ gl.puts
30
+ end
31
+ gl.close unless gl.closed?
32
+ end
33
+
34
+ task :generate_lib => generated_library
35
+
36
+ task :check_manifest => generated_library
37
+
38
+ task :test => generated_library
18
39
 
19
40
  # vim: syntax=Ruby
data/lib/rake_dotnet.rb CHANGED
@@ -1,3 +1,923 @@
1
- class Rake_dotnet
2
- VERSION = '0.0.1'
3
- end
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+
5
+ # Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by Peter Mounce (pete@neverrunwithscissors.com)
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to
9
+ # deal in the Software without restriction, including without limitation the
10
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
+ # sell copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
+ # IN THE SOFTWARE.
24
+
25
+ #++
26
+ #
27
+ # = Rake DotNet -- A collection of custom tasks for .NET build automation
28
+ #
29
+ # This is the main file for Rake DotNet custom tasks. Normally it is referenced
30
+ # as a library via a require statement, but it can be distributed
31
+ # independently as an application.
32
+
33
+ require 'rake'
34
+ require 'rake/tasklib'
35
+ require 'rake/clean'
36
+ require 'pathname'
37
+
38
+
39
+ desc "Displays this message; a list of tasks"
40
+ task :help do
41
+ taskHash = Hash[*(`rake.cmd -T`.split(/\n/).collect { |l| l.match(/rake (\S+)\s+\#\s(.+)/).to_a }.collect { |l| [l[1], l[2]] }).flatten]
42
+
43
+ indent = " "
44
+
45
+ puts "rake #{indent}#Runs the 'default' task"
46
+
47
+ taskHash.each_pair do |key, value|
48
+ if key.nil?
49
+ next
50
+ end
51
+ puts "rake #{key}#{indent.slice(0, indent.length - key.length)}##{value}"
52
+ end
53
+ end
54
+
55
+ def regexify(path)
56
+ path.gsub('/', '\/').gsub('.', '\.')
57
+ end
58
+
59
+ # Setting constants like this allows you to do things like 'rake compile CONFIGURATION=Release' to specify their values
60
+ # By default, we assume that this Rakefile lives in {PRODUCT_ROOT}/build, and that this is the working directory
61
+ PRODUCT_ROOT = ENV['PRODUCT_ROOT'] ? ENV['PRODUCT_ROOT'] : '..'
62
+ SRC_DIR = File.join(PRODUCT_ROOT, 'src')
63
+ TOOLS_DIR = ENV['TOOLS_DIR'] ? ENV['TOOLS_DIR'] : File.join(PRODUCT_ROOT, '..', '3rdparty')
64
+ CONFIGURATION = ENV['CONFIGURATION'] ? ENV['CONFIGURATION'] : 'Debug'
65
+ MSBUILD_VERBOSITY = ENV['MSBUILD_VERBOSITY'] ? ENV['MSBUILD_VERBOSITY'] : 'm'
66
+ OUT_DIR = ENV['OUT_DIR'] ? ENV['OUT_DIR'] : 'out'
67
+
68
+ # clean will remove intermediate files (like the output of msbuild; things in the src tree)
69
+ # clobber will remove build-output files (which will all live under the build tree)
70
+ CLEAN.exclude('**/core') # core files are a Ruby/*nix thing - dotNET developers are unlikely to generate them.
71
+ CLEAN.include("#{SRC_DIR}/**/obj")
72
+ CLEAN.include("#{SRC_DIR}/**/bin")
73
+ CLEAN.include("#{SRC_DIR}/**/AssemblyInfo.cs")
74
+ CLOBBER.include(OUT_DIR)
75
+
76
+
77
+ module Rake
78
+ class AssemblyInfoTask < Rake::TaskLib
79
+ attr_accessor :name, :product_name, :configuration, :company_name, :version
80
+
81
+ # Create an AssemblyInfo file-task; define a task to run it whose name is :assembly_info
82
+ def initialize(name) # :yield: self
83
+ @name = name
84
+ yield self if block_given?
85
+ define
86
+ end
87
+
88
+ # Create the tasks defined by this task lib.
89
+ def define
90
+ file @name do
91
+ template_file = Pathname.new(template)
92
+ content = template_file.read
93
+ token_replacements.each do |key,value|
94
+ content = content.gsub(/(\$\{#{key}\})/, value.to_s)
95
+ end
96
+ of = Pathname.new(@name)
97
+ of.delete if of.exist?
98
+ of.open('w') { |f| f.puts content }
99
+ end
100
+
101
+ desc 'Generate the AssemblyInfo.cs file from the template'
102
+ task :assembly_info => [@name]
103
+
104
+ self
105
+ end
106
+
107
+ def template
108
+ @template_file ||= @name.sub(/\.cs/, '.template.cs')
109
+ end
110
+
111
+ def token_replacements
112
+ r = {}
113
+ r[:built_on] = Time.now
114
+ r[:product] = product_name
115
+ r[:configuration] = configuration
116
+ r[:company] = company_name
117
+ r[:version] = version
118
+ return r
119
+ end
120
+
121
+ def product_name
122
+ @product_name ||= 'NRWS rake_dotnet'
123
+ end
124
+
125
+ def configuration
126
+ @configuration ||= 'Debug'
127
+ end
128
+
129
+ def company_name
130
+ @company_name ||= 'NRWS'
131
+ end
132
+
133
+ def version
134
+ @version ||= Versioner.new.get
135
+ end
136
+ end
137
+ end
138
+
139
+
140
+ module Rake
141
+ class FxCopTask < TaskLib
142
+ def initialize(params={})
143
+ @product_name = params[:product_name] || PRODUCT_NAME
144
+ @report_dir = params[:report_dir] || File.join(OUT_DIR, 'reports')
145
+ @name = params[:name] || File.join(@report_dir, @product_name + '.fxcop')
146
+ @suites_dir = params[:suites_dir] || File.join(OUT_DIR, 'bin')
147
+ @dll_list = FileList.new
148
+ @deps = params[:deps] || []
149
+ @fxcop_options = {:apply_out_xsl=>true, :out_xsl=>'CodeAnalysisReport.xsl'}.merge(params[:fxcop_options] || {})
150
+ if @fxcop_options[:apply_out_xsl].nil? || @fxcop_options[:apply_out_xsl] == false
151
+ @name += '.xml'
152
+ else
153
+ @name += '.html'
154
+ end
155
+ @fxcop_options[:out_file] = @name if @fxcop_options[:out_file].nil?
156
+
157
+ yield self if block_given?
158
+ define
159
+ end
160
+
161
+ def define
162
+ @deps.each do |d|
163
+ task :fxcop => d
164
+ end
165
+
166
+ directory @report_dir
167
+
168
+ file @name => [@report_dir] do |f|
169
+ runner = FxCop.new(@dll_list, @fxcop_options)
170
+ runner.run
171
+ end
172
+
173
+ task :fxcop,[:globs] do |t, args|
174
+ args.with_defaults(:globs => "#{@suites_dir}/**/*#{@product_name}*.dll")
175
+ @dll_list = FileList.new(args.globs)
176
+ Rake::FileTask[@name].invoke
177
+ end
178
+
179
+ self
180
+ end
181
+
182
+ self
183
+ end
184
+ end
185
+
186
+ class FxCop
187
+ attr_accessor :dlls, :out_file, :out_xsl, :apply_out_xsl, :dependencies_path, :summary, :verbose, :echo_to_console, :xsl_echo_to_console, :ignore_autogen, :culture
188
+
189
+ def initialize(dlls, params={})
190
+ @dlls = dlls
191
+
192
+ @exe_dir = params[:fxcop_exe_dir] || File.join(TOOLS_DIR, 'fxcop')
193
+ @exe = params[:fxcop_exe] || File.join(@exe_dir, 'fxcopcmd.exe')
194
+
195
+ @apply_out_xsl = params[:apply_out_xsl]
196
+ @culture = params[:culture]
197
+ @dependencies_path = params[:dependencies_path]
198
+ @echo_to_console = params[:echo_to_console]
199
+ @ignore_autogen = params[:ignore_autogen] || true
200
+ @out_file = params[:out_file]
201
+ @out_xsl = File.join(@exe_dir, 'Xml', params[:out_xsl]) unless params[:out_xsl].nil?
202
+ @summary = params[:summary]
203
+ @verbose = params[:verbose]
204
+ @xsl_echo_to_console = params[:xsl_echo_to_console]
205
+
206
+ yield self if block_given?
207
+ end
208
+
209
+ def console
210
+ '/console' if @echo_to_console || @out_file.nil?
211
+ end
212
+
213
+ def files_to_analyse
214
+ list = ''
215
+ @dlls.each do |dll|
216
+ list += "/file:\"#{dll}\" "
217
+ end
218
+ list = list.chop
219
+ end
220
+
221
+ def out_file
222
+ "/out:\"#{@out_file}\"" if @out_file
223
+ end
224
+
225
+ def out_xsl
226
+ "/outxsl:\"#{@out_xsl}\"" if @out_xsl
227
+ end
228
+
229
+ def apply_out_xsl
230
+ "/applyoutxsl" if @apply_out_xsl
231
+ end
232
+
233
+ def cmd
234
+ "\"#{@exe}\" #{files_to_analyse} #{console} #{out_file} #{out_xsl} #{apply_out_xsl}"
235
+ end
236
+
237
+ def run
238
+ sh cmd
239
+ end
240
+ end
241
+
242
+
243
+ module Rake
244
+ class HarvestOutputTask < TaskLib
245
+ def initialize(params={})
246
+ @src_path = params[:src_path] || File.join(PRODUCT_ROOT, 'src')
247
+ @target_path = params[:target_path] || File.join(OUT_DIR, 'bin')
248
+ @deps = params[:deps] || []
249
+ @configuration = params[:configuration] || 'Debug'
250
+ @glob = params[:glob] || "#{@src_path}/*"
251
+
252
+ yield self if block_given?
253
+ define
254
+ end
255
+
256
+ def define
257
+ directory @target_path
258
+
259
+ desc "Harvest specified libraries (or all matching #{@glob}) to #{@target_path}"
260
+ task :harvest_output,[:to_harvest_list] => @target_path do |t, args|
261
+ list = FileList.new
262
+ @glob.each do |g|
263
+ list.include(g)
264
+ end
265
+ args.with_defaults(:to_harvest_list => list)
266
+ args.to_harvest_list.each do |entry|
267
+ pn = Pathname.new(entry)
268
+ if pn.directory?
269
+ output = FileList.new
270
+ #TODO: distinguish between web and class and console output
271
+ output.include("#{entry}/bin/#{@configuration}/**/*")
272
+ output.include("#{entry}/bin/**/*")
273
+ output.each do |o|
274
+ o_pn = Pathname.new(o)
275
+ unless (o_pn.directory?)
276
+ to_pn = Pathname.new("#{@target_path}/#{o_pn.basename}")
277
+ cp(o, to_pn) unless to_pn.exist?
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end
283
+
284
+ @deps.each do |d|
285
+ task :harvest => d
286
+ end
287
+
288
+ self
289
+ end
290
+ end
291
+
292
+ class HarvestWebApplicationTask < TaskLib
293
+ def initialize(params={})
294
+ @src_path = params[:src_path] || File.join(PRODUCT_ROOT, 'src')
295
+ @target_path = params[:target_path] || OUT_DIR
296
+ @deps = params[:deps] || []
297
+ @glob = params[:glob] || '*Site*'
298
+
299
+ yield self if block_given?
300
+ define
301
+ end
302
+
303
+ def define
304
+ out_dir_regex = regexify(@target_path)
305
+
306
+ rule(/#{out_dir_regex}\/[\w\.-_ ]*Site[\w\.-_ ]*\//) do |r|
307
+ web_app_name = r.name.match(/#{out_dir_regex}\/([\w\.-_ ]*Site[\w\.-_ ]*)\//)[1]
308
+ src = File.join(@src_path, web_app_name)
309
+ svn = SvnExport.new(src, r.name)
310
+ svn.export
311
+ cp_r(File.join(src, 'bin'), r.name)
312
+ end
313
+
314
+ desc "Harvest specified web-applications (or all matching #{@src_path}/#{@glob}) to #{@target_path}"
315
+ task :harvest_webapps,[:web_app_list] => @target_path do |t, args|
316
+ list = FileList.new("#{@src_path}/#{@glob}")
317
+ args.with_defaults(:web_app_list => list)
318
+ args.web_app_list.each do |w|
319
+ pn = Pathname.new(w)
320
+ out = File.join(@target_path, pn.basename) + '/'
321
+ Rake::FileTask[out].invoke
322
+ end
323
+ end
324
+
325
+ @deps.each do |d|
326
+ task :harvest_webapps => d
327
+ end
328
+
329
+ self
330
+ end
331
+ end
332
+ end
333
+
334
+ class Harvester
335
+ attr_accessor :files, :target
336
+
337
+ def initialize
338
+ @files = Hash.new
339
+ end
340
+
341
+ def add(glob)
342
+ toAdd = Dir.glob(glob)
343
+ toAdd.each do |a|
344
+ pn = Pathname.new(a)
345
+ @files[pn.basename.to_s] = pn
346
+ end
347
+ end
348
+
349
+ def harvest(target)
350
+ mkdir_p(target) unless File.exist?(target)
351
+ @files.sort.each do |k, v|
352
+ cp(v, target)
353
+ end
354
+ end
355
+
356
+ def list
357
+ @files.sort.each do |k, v|
358
+ puts k + ' -> ' + v
359
+ end
360
+ end
361
+ end
362
+
363
+
364
+ module Rake
365
+ class MsBuildTask < TaskLib
366
+ attr_accessor :src_dir, :verbosity, :working_dir
367
+
368
+ def initialize(params={})
369
+ @configuration = params[:configuration] || CONFIGURATION
370
+ @src_dir = params[:src_dir] || File.join(PRODUCT_ROOT, 'src')
371
+ @verbosity = params[:verbosity] || 'm'
372
+ @working_dir = params[:working_dir] || '.'
373
+ @deps = params[:deps] || []
374
+
375
+ yield self if block_given?
376
+ define
377
+ end
378
+
379
+ def define
380
+ # most project types put output into bin/{configuration}
381
+ rule(/#{src_dir_regex}\/[\w\.]+\/bin\/#{@configuration}\/[\w\.]+\.(?:dll|exe)/) do |r|
382
+ pn = Pathname.new(r.name)
383
+ name = pn.basename.to_s.sub('.dll', '')
384
+ project = File.join(@src_dir, name, name + '.csproj')
385
+ mb = MsBuild.new(project, {:Configuration => @configuration}, ['Build'], verbosity, @working_dir)
386
+ mb.run
387
+ end
388
+
389
+ # web application projects put output into /bin
390
+ rule(/#{src_dir_regex}\/[\w\.]+\/bin\/[\w\.]+\.dll/) do |r|
391
+ pn = Pathname.new(r.name)
392
+ name = pn.basename.to_s.sub('.dll', '')
393
+ project = File.join(@src_dir, name, name + '.csproj')
394
+ mb = MsBuild.new(project, {:Configuration => @configuration}, ['Build'], verbosity, @working_dir)
395
+ mb.run
396
+ end
397
+
398
+ desc "Compile the specified projects (give relative paths) (otherwise, all matching src/**/*.*proj)"
399
+ task :compile,[:projects] do |t, args|
400
+ project_list = FileList.new("#{src_dir}/**/*.*proj")
401
+ args.with_defaults(:projects => project_list)
402
+ args.projects.each do |p|
403
+ pn = Pathname.new(p)
404
+ # TODO: Figure out which type of project we are so we can invoke the correct rule, with the correct output extension
405
+ dll = File.join(pn.dirname, 'bin', @configuration, pn.basename.sub(pn.extname, '.dll'))
406
+ Rake::FileTask[dll].invoke
407
+ end
408
+ end
409
+
410
+ @deps.each do |d|
411
+ task :compile => d
412
+ end
413
+
414
+ self
415
+ end
416
+
417
+ def src_dir_regex
418
+ regexify(@src_dir)
419
+ end
420
+
421
+ def figure_out_project_type(project_pathname)
422
+ # TODO.
423
+ end
424
+ end
425
+ end
426
+
427
+ class MsBuild
428
+ attr_accessor :project, :properties, :targets, :verbosity
429
+
430
+ def initialize(project='default.proj', properties={}, targets=[], verbosity='n', working_dir=nil)
431
+ @project = project
432
+ @properties = properties
433
+ @targets = targets
434
+ @verbosity = verbosity
435
+ @working_dir = working_dir
436
+ @exe = '"' + File.join(ENV['windir'].dup, 'Microsoft.NET', 'Framework', 'v3.5', 'msbuild.exe') + '"'
437
+ end
438
+
439
+ def cmd
440
+ "#{@exe} #{project} /maxcpucount /v:#{@verbosity} /property:BuildInParallel=true /p:#{properties} /t:#{targets}"
441
+ end
442
+
443
+ def run
444
+ if @working_dir
445
+ chdir(@working_dir) do
446
+ sh cmd
447
+ end
448
+ end
449
+ end
450
+
451
+ def project
452
+ "\"#{@project}\""
453
+ end
454
+
455
+ def targets
456
+ @targets.join(';')
457
+ end
458
+
459
+ def properties
460
+ p = []
461
+ @properties.each {|key, value| p.push("#{key}=#{value}") }
462
+ p.join(';')
463
+ end
464
+ end
465
+
466
+
467
+ module Rake
468
+ class NCoverTask < TaskLib
469
+ def initialize(params={})
470
+
471
+ @product_name = params[:product_name] || PRODUCT_NAME
472
+ @bin_dir = params[:bin_dir] || File.join(OUT_DIR, 'bin')
473
+ @report_dir = params[:report_dir] || File.join(OUT_DIR, 'reports')
474
+ @deps = params[:deps] || []
475
+ tool_defaults = {:arch => 'x86'}
476
+ @ncover_options = tool_defaults.merge(params[:ncover_options] || {})
477
+ @ncover_reporting_options = tool_defaults.merge(params[:ncover_reporting_options] || {})
478
+
479
+ yield self if block_given?
480
+ define
481
+ end
482
+
483
+ def define
484
+ @deps.each do |d|
485
+ task :ncover_profile => d
486
+ end
487
+
488
+ directory @report_dir
489
+
490
+ reports_dir_regex = regexify(@report_dir)
491
+ rule(/#{reports_dir_regex}\/.*\.coverage\.xml/) do |r|
492
+ dll_to_execute = r.name.sub(/#{@report_dir}\/(.*)\.coverage\.xml/, "#{@bin_dir}/\\1.dll")
493
+ nc = NCover.new(@report_dir, dll_to_execute, @ncover_options)
494
+ nc.run
495
+ end
496
+
497
+ desc "Generate ncover coverage XML, one file per test-suite that exercises your product"
498
+ task :ncover_profile,[:dlls_to_run] => [@report_dir] do |t, args|
499
+ dlls_to_run_list = FileList.new
500
+ dlls_to_run_list.include("#{@bin_dir}/**/*#{@product_name}*Tests*.dll")
501
+ dlls_to_run_list.include("#{@bin_dir}/**/*#{@product_name}*Tests*.exe")
502
+ args.with_defaults(:dlls_to_run => dlls_to_run_list)
503
+ args.dlls_to_run.each do |d|
504
+ dll_to_run = Pathname.new(d)
505
+ cf_name = dll_to_run.basename.sub(dll_to_run.extname, '.coverage.xml')
506
+ coverage_file = File.join(@report_dir, cf_name)
507
+ Rake::FileTask[coverage_file].invoke
508
+ end
509
+
510
+ end
511
+
512
+ ncover_summary_report_html = File.join(@report_dir, 'merged.MethodSourceCodeClassMethod.coverage-report.html')
513
+ file ncover_summary_report_html do
514
+ # ncover lets us use *.coverage.xml to merge together files
515
+ include = [File.join(@report_dir, '*.coverage.xml')]
516
+ @ncover_reporting_options[:name] = 'merged'
517
+ ncr = NCoverReporting.new(@report_dir, include, @ncover_reporting_options)
518
+ ncr.run
519
+ end
520
+
521
+ desc "Generate ncover coverage summary HTML report, on all coverage files, merged together"
522
+ task :ncover_summary => [:ncover_profile, ncover_summary_report_html]
523
+
524
+ task :clean_coverage do
525
+ rm_rf 'out/reports/*coverage-report*'
526
+ end
527
+
528
+ self
529
+ end
530
+
531
+ self
532
+ end
533
+ end
534
+
535
+ class NCover
536
+ def initialize(report_dir, dll_to_execute, params)
537
+ params ||= {}
538
+ arch = params[:arch] || 'x86'
539
+ @exe = params[:ncover_exe] || File.join(TOOLS_DIR, 'ncover', arch, 'ncover.console.exe')
540
+ @dll_to_execute = dll_to_execute
541
+ ofname = File.split(dll_to_execute)[1].sub(/(\.dll)/, '') + '.coverage.xml'
542
+ @output_file = File.join(report_dir, ofname)
543
+ @exclude_assemblies_regex = params[:exclude_assemblies_regex] || '.*Tests.*'
544
+ @build_id = params[:build_id] || RDNVERSION
545
+ end
546
+
547
+ def cmdToRun
548
+ x = XUnit.new(@dll_to_execute, {})
549
+ x.cmd
550
+ end
551
+
552
+ def bi
553
+ "//bi #{@build_id.to_s}"
554
+ end
555
+
556
+ def eas
557
+ "//eas #{@exclude_assemblies_regex}"
558
+ end
559
+
560
+ def cmd
561
+ "\"#{@exe}\" #{cmdToRun} //x #{@output_file} #{eas} #{bi}"
562
+ end
563
+
564
+ def run
565
+ sh cmd
566
+ end
567
+ end
568
+
569
+ class NCoverReporting
570
+ def initialize(report_dir, coverage_files, params)
571
+ @report_dir = report_dir
572
+ @coverage_files = coverage_files || []
573
+
574
+ params ||= {}
575
+ arch = params[:arch] || 'x86'
576
+ @exe = params[:ncover_reporting_exe] || File.join(TOOLS_DIR, 'ncover', arch, 'ncover.reporting.exe')
577
+
578
+ # required
579
+ @name = params[:name] || 'CoverageReport'
580
+ @report = params[:report] || 'MethodSourceCodeClassMethod'
581
+ @format = params[:report_format] || 'html' # can be xml or html
582
+ @output_path = File.join(@report_dir, @name + '.' + @report + '.' + @format)
583
+
584
+ # optional
585
+ @build_id = params[:build_id] || RDNVERSION
586
+ @so = params[:sort] || 'CoveragePercentageAscending'
587
+ end
588
+
589
+ def coverage_files
590
+ list = ''
591
+ @coverage_files.each do |cf|
592
+ list += "\"#{cf}\" "
593
+ end
594
+ list
595
+ end
596
+
597
+ def bi
598
+ "//bi #{@build_id.to_s}"
599
+ end
600
+
601
+ def r
602
+ "//r #{@report}"
603
+ end
604
+
605
+ def op
606
+ "//op \"#{@output_path}\""
607
+ end
608
+
609
+ def so
610
+ "//so #{@so}"
611
+ end
612
+
613
+ def cmd
614
+ "\"#{@exe}\" #{coverage_files} #{bi} #{r} #{op} #{so}"
615
+ end
616
+
617
+ def run
618
+ sh cmd
619
+ end
620
+ end
621
+
622
+
623
+ module Rake
624
+ class RDNPackageTask < TaskLib
625
+ attr_accessor :targets
626
+
627
+ def initialize(name, version, params={})
628
+ @name = name
629
+ @version = version
630
+ @out_dir = params[:out_dir] || OUT_DIR
631
+ @deps = params[:deps] || []
632
+ @configuration = params[:configuration] || CONFIGURATION
633
+ globs = params[:globs] || []
634
+ @targets = FileList.new globs
635
+
636
+ yield self if block_given?
637
+ define
638
+ end
639
+
640
+ def define
641
+ pkg = File.join(@out_dir, 'pkg')
642
+ pkg_root = renamed(File.join(pkg, @name))
643
+
644
+ directory pkg
645
+ directory pkg_root
646
+
647
+ package_file = pkg_root + '.zip'
648
+ package_file_regex = regexify(package_file)
649
+
650
+ @deps.each do |d|
651
+ file package_file => d
652
+ task :package => d
653
+ end
654
+
655
+ rule(/#{package_file_regex}/) do |r|
656
+ @targets.each do |t|
657
+ f = Pathname.new(t)
658
+ if f.directory?
659
+ mv "#{t}/*", pkg_root
660
+ else
661
+ mv t, pkg_root
662
+ end
663
+ end
664
+ snipped = pkg_root.sub(pkg + '/', '')
665
+ chdir pkg do
666
+ sz = SevenZip.new('../../'+package_file, snipped, {:sevenzip=>File.join('..','..',TOOLS_DIR, '7zip', '7z.exe')})
667
+ sz.run_add
668
+ end
669
+ end
670
+
671
+ directory @out_dir
672
+
673
+ desc "Generate zip'd packages for all package-tasks"
674
+ task :package => [@out_dir, pkg, pkg_root, package_file]
675
+
676
+ desc "Delete all packages"
677
+ task :clobber_package do
678
+ rm_rf pkg
679
+ end
680
+
681
+ task :clobber => :clobber_package
682
+
683
+ desc "Delete all packages and recreate them"
684
+ task :repackage => [:clobber_package, :package]
685
+
686
+ self
687
+ end
688
+
689
+ def renamed(target)
690
+ "#{target}-#{@configuration}-v#{@version}"
691
+ end
692
+ end
693
+ end
694
+
695
+
696
+ class SevenZip
697
+ def initialize(archive_name, file_names, opts={})
698
+ @exe = opts[:sevenzip] || File.join(TOOLS_DIR, '7zip', '7z.exe')
699
+ @archive_name = archive_name
700
+ @file_names = file_names
701
+
702
+ yield self if block_given?
703
+ end
704
+
705
+ def cmd_add
706
+ "#{exe} a #{switches} #{archive_name} #{file_names}"
707
+ end
708
+
709
+ def run_add
710
+ sh cmd_add
711
+ end
712
+
713
+ def archive_name
714
+ "\"#{@archive_name}\""
715
+ end
716
+
717
+ def file_names
718
+ if @file_names.is_a? String
719
+ "\"#{@file_names}\""
720
+ elsif @file_names.is_a? Array
721
+ list = ''
722
+ @file_names.each do |fn|
723
+ list += "\"#{fn}\" "
724
+ end
725
+ list.chop
726
+ end
727
+ end
728
+
729
+ def exe
730
+ "\"#{@exe}\""
731
+ end
732
+
733
+ def switches
734
+
735
+ end
736
+ end
737
+
738
+
739
+ class Svn
740
+ attr_accessor :svn
741
+
742
+ def initialize(opts={})
743
+ @svn = opts[:svn] || File.join(TOOLS_DIR, 'svn', 'bin', 'svn.exe')
744
+ yield self if block_given?
745
+ end
746
+
747
+ def exe
748
+ "\"#{@svn}\""
749
+ end
750
+ end
751
+
752
+ class SvnExport < Svn
753
+ def initialize(src, dest, opts={})
754
+ super(opts)
755
+ @src = src
756
+ @dest = dest
757
+ end
758
+
759
+ def cmd
760
+ "#{exe} export #{src} #{dest}"
761
+ end
762
+
763
+ def export
764
+ sh cmd
765
+ end
766
+
767
+ def src
768
+ "\"#{@src}\""
769
+ end
770
+
771
+ def dest
772
+ "\"#{@dest}\""
773
+ end
774
+ end
775
+
776
+ class SvnInfo < Svn
777
+ attr_accessor :svn
778
+
779
+ def initialize(opts)
780
+ super(opts)
781
+ @path = opts[:path] || '.'
782
+ yield self if block_given?
783
+ end
784
+
785
+ def cmd
786
+ "#{exe} info #{path}"
787
+ end
788
+
789
+ def revision
790
+ out = `#{cmd}`
791
+ out.match(/Revision: (\d+)/)[1]
792
+ end
793
+
794
+ def path
795
+ "\"#{@path}\""
796
+ end
797
+ end
798
+
799
+
800
+ class Versioner
801
+ def initialize(template_file=nil)
802
+ tf = template_file || 'version.template.txt'
803
+ template_file = Pathname.new(tf)
804
+ @maj_min = template_file.read.chomp
805
+ @build = ENV['BUILD_NUMBER'] || 0
806
+ @svn_info = SvnInfo.new(:path => '.')
807
+ end
808
+
809
+ def get
810
+ "#{@maj_min}.#{@build}.#{@svn_info.revision}"
811
+ end
812
+ end
813
+
814
+
815
+
816
+
817
+ module Rake
818
+ class XUnitTask < TaskLib
819
+ attr_accessor :suites_dir, :reports_dir, :options
820
+
821
+ def initialize(params={}) # :yield: self
822
+ @suites_dir = params[:suites_dir] || File.join(OUT_DIR, 'bin')
823
+ @reports_dir = params[:reports_dir] || File.join(OUT_DIR, 'reports')
824
+ @options = params[:options] || {}
825
+ @deps = params[:deps] || []
826
+
827
+ yield self if block_given?
828
+ define
829
+ end
830
+
831
+ # Create the tasks defined by this task lib.
832
+ def define
833
+ @deps.each do |d|
834
+ task :xunit => d
835
+ end
836
+
837
+ rule(/#{@reports_dir}\/.*Tests.*\//) do |r|
838
+ suite = r.name.match(/.*\/(.*Tests)\//)[1]
839
+ testsDll = File.join(@suites_dir, suite + '.dll')
840
+ out_dir = File.join(@reports_dir, suite)
841
+ unless File.exist?(out_dir) && uptodate?(testsDll, out_dir)
842
+ mkdir_p(out_dir) unless File.exist?(out_dir)
843
+ x = XUnit.new(testsDll, out_dir, nil, options=@options)
844
+ x.run
845
+ end
846
+ end
847
+
848
+ directory @reports_dir
849
+
850
+ desc "Generate test reports (which ones, depends on the content of XUNIT_OPTS) inside of each directory specified, where each directory matches a test-suite name (give relative paths) (otherwise, all matching #{@suites_dir}/*Tests.*.dll) and write reports to #{@reports_dir}"
851
+ task :xunit,[:reports] => [@reports_dir] do |t, args|
852
+ reports_list = FileList.new("#{@suites_dir}/**/*Tests*.dll").pathmap("#{@reports_dir}/%n/")
853
+ args.with_defaults(:reports => reports_list)
854
+ args.reports.each do |r|
855
+ Rake::FileTask[r].invoke
856
+ end
857
+ end
858
+
859
+ task :xunit_clobber do
860
+ rm_rf(@reports_dir)
861
+ end
862
+
863
+ self
864
+ end
865
+ end
866
+ end
867
+
868
+ class XUnit
869
+ attr_accessor :xunit, :testDll, :reports_dir, :options
870
+
871
+ def initialize(testDll, reports_dir, xunit=nil, options={})
872
+ @xunit = xunit || File.join(TOOLS_DIR, 'xunit', 'xunit.console.exe')
873
+ @testDll = testDll
874
+ @reports_dir = reports_dir
875
+ @options = options
876
+ end
877
+
878
+ def run
879
+ sh cmd
880
+ end
881
+
882
+ def cmd
883
+ cmd = "#{exe} #{testDll} #{html} #{xml} #{nunit} #{wait} #{noshadow} #{teamcity}"
884
+ end
885
+
886
+ def exe
887
+ "\"#{@xunit}\""
888
+ end
889
+
890
+ def suite
891
+ @testDll.match(/.*\/([\w\.]+)\.dll/)[1]
892
+ end
893
+
894
+ def testDll
895
+ "\"#{@testDll}\""
896
+ end
897
+
898
+ def html
899
+ "/html #{@reports_dir}/#{suite}.test-results.html" if @options.has_key?(:html)
900
+ end
901
+
902
+ def xml
903
+ "/xml #{@reports_dir}/#{suite}.test-results.xml" if @options.has_key?(:xml)
904
+ end
905
+
906
+ def nunit
907
+ "/nunit #{@reports_dir}/#{suite}.test-results.nunit.xml" if @options.has_key?(:nunit)
908
+ end
909
+
910
+ def wait
911
+ '/wait' if @options.has_key?(:wait)
912
+ end
913
+
914
+ def noshadow
915
+ '/noshadow' if @options.has_key?(:noshadow)
916
+ end
917
+
918
+ def teamcity
919
+ '/teamcity' if @options.has_key?(:teamcity)
920
+ end
921
+ end
922
+
923
+
@@ -0,0 +1,16 @@
1
+ require 'test/unit'
2
+ require 'lib/rake_dotnet.rb'
3
+
4
+ class SvnTest < Test::Unit::TestCase
5
+ def test_initialize_with_no_opts
6
+ svn = Svn.new
7
+
8
+ assert_equal "\"#{TOOLS_DIR}/svn/bin/svn.exe\"", svn.exe
9
+ end
10
+
11
+ def test_initialize_with_path
12
+ svn = Svn.new :svn => 'foo/bar/svn.exe'
13
+
14
+ assert_equal "\"foo/bar/svn.exe\"", svn.exe
15
+ end
16
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rake-dotnet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter MouncePeter Mounce
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-09 00:00:00 +00:00
12
+ date: 2009-03-26 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,12 +30,12 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.9.0
33
+ version: 1.11.0
34
34
  version:
35
35
  description: Making a .NET build-automation dev's life easier, one angle-bracket at a time
36
36
  email: pete@neverrunwithscissors.compete@neverrunwithscissors.com
37
- executables:
38
- - rake_dotnet
37
+ executables: []
38
+
39
39
  extensions: []
40
40
 
41
41
  extra_rdoc_files:
@@ -47,7 +47,6 @@ files:
47
47
  - Manifest.txt
48
48
  - README.txt
49
49
  - Rakefile
50
- - bin/rake_dotnet
51
50
  - lib/rake_dotnet.rb
52
51
  - test/test_rake_dotnet.rb
53
52
  has_rdoc: true
data/bin/rake_dotnet DELETED
File without changes