rake-dotnet 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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