rake-funnel 0.0.1.pre
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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/.travis.yml +21 -0
- data/Gemfile +29 -0
- data/Guardfile +24 -0
- data/README.md +29 -0
- data/Rakefile +77 -0
- data/build.cmd +30 -0
- data/bundle.cmd +26 -0
- data/config/.gitignore +1 -0
- data/config/.local.yaml.example +9 -0
- data/config/default.yaml +5 -0
- data/config/dev.yaml +0 -0
- data/config/production.yaml +3 -0
- data/lib/rake/funnel/ambiguous_file_error.rb +29 -0
- data/lib/rake/funnel/execution_error.rb +26 -0
- data/lib/rake/funnel/extensions/camel_case.rb +19 -0
- data/lib/rake/funnel/extensions/common_path.rb +52 -0
- data/lib/rake/funnel/extensions/disable_colors.rb +27 -0
- data/lib/rake/funnel/extensions/rexml.rb +23 -0
- data/lib/rake/funnel/extensions/shell.rb +56 -0
- data/lib/rake/funnel/framework.rb +15 -0
- data/lib/rake/funnel/integration/progress_report.rb +70 -0
- data/lib/rake/funnel/integration/sync_output.rb +8 -0
- data/lib/rake/funnel/integration/teamcity/nunit_plugin.rb +59 -0
- data/lib/rake/funnel/integration/teamcity/progress_report.rb +33 -0
- data/lib/rake/funnel/integration/teamcity/service_messages.rb +40 -0
- data/lib/rake/funnel/integration/teamcity/teamcity.rb +15 -0
- data/lib/rake/funnel/integration/teamcity.rb +5 -0
- data/lib/rake/funnel/support/finder.rb +51 -0
- data/lib/rake/funnel/support/mapper.rb +81 -0
- data/lib/rake/funnel/support/mapper_styles/default.rb +31 -0
- data/lib/rake/funnel/support/mapper_styles/msbuild.rb +33 -0
- data/lib/rake/funnel/support/mapper_styles/msdeploy.rb +47 -0
- data/lib/rake/funnel/support/mapper_styles/nunit.rb +33 -0
- data/lib/rake/funnel/support/mono.rb +17 -0
- data/lib/rake/funnel/support/patch.rb +37 -0
- data/lib/rake/funnel/support/template_engine.rb +26 -0
- data/lib/rake/funnel/support/which.rb +15 -0
- data/lib/rake/funnel/tasks/bin_path.rb +34 -0
- data/lib/rake/funnel/tasks/copy.rb +54 -0
- data/lib/rake/funnel/tasks/environments.rb +74 -0
- data/lib/rake/funnel/tasks/environments_support/loader.rb +37 -0
- data/lib/rake/funnel/tasks/msbuild.rb +52 -0
- data/lib/rake/funnel/tasks/msbuild_support/build_tool.rb +28 -0
- data/lib/rake/funnel/tasks/msdeploy.rb +58 -0
- data/lib/rake/funnel/tasks/msdeploy_support/registry_patch.rb +84 -0
- data/lib/rake/funnel/tasks/nunit.rb +46 -0
- data/lib/rake/funnel/tasks/paket.rb +39 -0
- data/lib/rake/funnel/tasks/quick_template.rb +45 -0
- data/lib/rake/funnel/tasks/side_by_side_specs.rb +33 -0
- data/lib/rake/funnel/tasks/side_by_side_specs_support/remover.rb +62 -0
- data/lib/rake/funnel/tasks/timing.rb +100 -0
- data/lib/rake/funnel/tasks/timing_support/report.rb +89 -0
- data/lib/rake/funnel/tasks/timing_support/statistics.rb +26 -0
- data/lib/rake/funnel/tasks/zip.rb +66 -0
- data/lib/rake/funnel/version.rb +5 -0
- data/lib/rake/funnel.rb +7 -0
- data/rake-funnel.gemspec +28 -0
- data/spec/rake/funnel/execution_error_spec.rb +67 -0
- data/spec/rake/funnel/extensions/camel_case_spec.rb +17 -0
- data/spec/rake/funnel/extensions/common_path_spec.rb +56 -0
- data/spec/rake/funnel/extensions/disable_colors_spec.rb +33 -0
- data/spec/rake/funnel/extensions/rexml_spec.rb +20 -0
- data/spec/rake/funnel/extensions/shell_spec.rb +237 -0
- data/spec/rake/funnel/integration/progress_report_spec.rb +149 -0
- data/spec/rake/funnel/integration/sync_output_spec.rb +16 -0
- data/spec/rake/funnel/integration/teamcity/nunit_plugin_spec.rb +112 -0
- data/spec/rake/funnel/integration/teamcity/progress_report_spec.rb +174 -0
- data/spec/rake/funnel/integration/teamcity/service_messages_spec.rb +136 -0
- data/spec/rake/funnel/integration/teamcity/teamcity_spec.rb +34 -0
- data/spec/rake/funnel/support/finder_spec.rb +210 -0
- data/spec/rake/funnel/support/mapper_spec.rb +87 -0
- data/spec/rake/funnel/support/mapper_styles/msdeploy_spec.rb +222 -0
- data/spec/rake/funnel/support/mapper_styles/nunit_spec.rb +25 -0
- data/spec/rake/funnel/support/mapper_styles/styles_spec.rb +214 -0
- data/spec/rake/funnel/support/mono_spec.rb +57 -0
- data/spec/rake/funnel/support/patch_spec.rb +108 -0
- data/spec/rake/funnel/support/template_engine_spec.rb +65 -0
- data/spec/rake/funnel/support/which_spec.rb +65 -0
- data/spec/rake/funnel/tasks/bin_path_spec.rb +40 -0
- data/spec/rake/funnel/tasks/copy_spec.rb +101 -0
- data/spec/rake/funnel/tasks/environments_spec.rb +237 -0
- data/spec/rake/funnel/tasks/environments_support/loader_spec.rb +114 -0
- data/spec/rake/funnel/tasks/msbuild_spec.rb +91 -0
- data/spec/rake/funnel/tasks/msbuild_support/build_tool_spec.rb +21 -0
- data/spec/rake/funnel/tasks/msdeploy_spec.rb +243 -0
- data/spec/rake/funnel/tasks/msdeploy_support/registry_patch_spec.rb +139 -0
- data/spec/rake/funnel/tasks/nunit_spec.rb +76 -0
- data/spec/rake/funnel/tasks/paket_spec.rb +184 -0
- data/spec/rake/funnel/tasks/quick_template_spec.rb +89 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_spec.rb +58 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_support/example/FooCode.cs +0 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_support/example/FooSpecs.cs +0 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_support/example/Sample.csproj +28 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_support/example/Specs.cs +0 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_support/example/subdir/BarCode.cs +0 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_support/example/subdir/BarSpecs.cs +0 -0
- data/spec/rake/funnel/tasks/side_by_side_specs_support/remover_spec.rb +116 -0
- data/spec/rake/funnel/tasks/timing_spec.rb +133 -0
- data/spec/rake/funnel/tasks/timing_support/report_spec.rb +129 -0
- data/spec/rake/funnel/tasks/zip_spec.rb +119 -0
- data/spec/spec_helper.rb +32 -0
- data/tools/MSDeploy/Microsoft.Web.Delegation.dll +0 -0
- data/tools/MSDeploy/Microsoft.Web.Deployment.Tracing.dll +0 -0
- data/tools/MSDeploy/Microsoft.Web.Deployment.dll +0 -0
- data/tools/MSDeploy/en/msdeploy.resources.dll +0 -0
- data/tools/MSDeploy/msdeploy.exe +0 -0
- data/tools/MSDeploy/msdeploy.exe.config +6 -0
- metadata +253 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'rake/tasklib'
|
|
2
|
+
|
|
3
|
+
Dir["#{File.dirname(__FILE__)}/msbuild_support/*.rb"].each do |path|
|
|
4
|
+
require path
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module Rake::Funnel::Tasks
|
|
8
|
+
class MSBuild < Rake::TaskLib
|
|
9
|
+
attr_accessor :name, :project_or_solution, :args, :search_pattern
|
|
10
|
+
|
|
11
|
+
def initialize(name = :compile)
|
|
12
|
+
@name = name
|
|
13
|
+
@args = {}
|
|
14
|
+
@search_pattern = %w(**/*.sln)
|
|
15
|
+
|
|
16
|
+
yield self if block_given?
|
|
17
|
+
define
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def msbuild
|
|
21
|
+
@_msbuild || MSBuildSupport::BuildTool.find
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def msbuild=(value)
|
|
25
|
+
@_msbuild = value
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def project_or_solution
|
|
29
|
+
Rake::Funnel::Support::Finder.new(@_project_or_solution || search_pattern, self, 'No projects or more than one project found.')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def project_or_solution=(value)
|
|
33
|
+
@_project_or_solution = value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
def define
|
|
38
|
+
desc "Compile #{project_or_solution.single_or_default}"
|
|
39
|
+
task @name do
|
|
40
|
+
cmd = [
|
|
41
|
+
msbuild,
|
|
42
|
+
project_or_solution.single,
|
|
43
|
+
*Rake::Funnel::Support::Mapper.new(:MSBuild).map(args)
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
sh(*cmd)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
self
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Rake::Funnel::Tasks::MSBuildSupport
|
|
2
|
+
class BuildTool
|
|
3
|
+
class << self
|
|
4
|
+
def find
|
|
5
|
+
if Rake::Win32.windows?
|
|
6
|
+
require 'win32/registry'
|
|
7
|
+
|
|
8
|
+
%w{12.0 4.0 3.5 2.0}.collect { |version|
|
|
9
|
+
msbuild = nil
|
|
10
|
+
key = "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\#{version}"
|
|
11
|
+
|
|
12
|
+
begin
|
|
13
|
+
Win32::Registry::HKEY_LOCAL_MACHINE.open(key) do |reg|
|
|
14
|
+
candidate = "#{reg['MSBuildToolsPath']}\\msbuild.exe"
|
|
15
|
+
msbuild = candidate if File.exists?(candidate)
|
|
16
|
+
end
|
|
17
|
+
rescue
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
msbuild
|
|
21
|
+
}.compact.first
|
|
22
|
+
else
|
|
23
|
+
'xbuild'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'rake/clean'
|
|
2
|
+
require 'rake/tasklib'
|
|
3
|
+
|
|
4
|
+
Dir["#{File.dirname(__FILE__)}/msdeploy_support/*.rb"].each do |path|
|
|
5
|
+
require path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Rake::Funnel::Tasks
|
|
9
|
+
class MSDeploy < Rake::TaskLib
|
|
10
|
+
attr_accessor :name, :msdeploy, :log_file, :args
|
|
11
|
+
|
|
12
|
+
def initialize(name = :msdeploy)
|
|
13
|
+
@name = name
|
|
14
|
+
@msdeploy = 'msdeploy'
|
|
15
|
+
@args = {}
|
|
16
|
+
|
|
17
|
+
yield self if block_given?
|
|
18
|
+
define
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def log_file
|
|
22
|
+
@log_file || "#{@name}.log"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
def define
|
|
27
|
+
CLEAN.include(log_file)
|
|
28
|
+
|
|
29
|
+
desc "Deploy #{deploy_source(args)}"
|
|
30
|
+
task @name do
|
|
31
|
+
mapper = Rake::Funnel::Support::Mapper.new(:MSDeploy)
|
|
32
|
+
cmd = [quote(msdeploy), mapper.map(args)]
|
|
33
|
+
.flatten
|
|
34
|
+
.join(' ')
|
|
35
|
+
|
|
36
|
+
MSDeploySupport::RegistryPatch.new do
|
|
37
|
+
shell(cmd, log_file: log_file, error_lines: /^(error|[\w\.]*exception)/i)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def deploy_source(args)
|
|
45
|
+
source = (args || {}).fetch(:source, {})
|
|
46
|
+
path = source.first
|
|
47
|
+
return if path.nil?
|
|
48
|
+
|
|
49
|
+
Pathname.new(path[1]).relative_path_from(Pathname.new('.').realpath) rescue path[1]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def quote(value)
|
|
53
|
+
value = value.gsub(/"/, '""') if value.kind_of?(String)
|
|
54
|
+
return %Q{"#{value}"} if value =~ /\s/
|
|
55
|
+
value
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module Rake::Funnel::Tasks::MSDeploySupport
|
|
2
|
+
class RegistryPatch
|
|
3
|
+
KEYS = [
|
|
4
|
+
'SOFTWARE\Microsoft\IIS Extensions\MSDeploy\3',
|
|
5
|
+
'SOFTWARE\Wow6432Node\Microsoft\IIS Extensions\MSDeploy\3'
|
|
6
|
+
]
|
|
7
|
+
VERSION_VALUE = 'Version'
|
|
8
|
+
FAKE_VERSION = '99.0.0.0'
|
|
9
|
+
|
|
10
|
+
def initialize(&block)
|
|
11
|
+
begin
|
|
12
|
+
patch.apply!
|
|
13
|
+
yield block if block_given?
|
|
14
|
+
ensure
|
|
15
|
+
patch.revert!
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
def patch
|
|
21
|
+
@patch ||= create_patch
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def root
|
|
25
|
+
Win32::Registry::HKEY_LOCAL_MACHINE
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete_key(key)
|
|
29
|
+
return nil unless key.created?
|
|
30
|
+
|
|
31
|
+
keyname = key.keyname
|
|
32
|
+
Proc.new {
|
|
33
|
+
root.create(File.dirname(keyname)) do |r|
|
|
34
|
+
r.delete_key(File.basename(keyname), true)
|
|
35
|
+
end
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete_value(key, value)
|
|
40
|
+
keyname = key.keyname
|
|
41
|
+
Proc.new {
|
|
42
|
+
root.create(keyname) do |r|
|
|
43
|
+
r.delete_value(value)
|
|
44
|
+
end
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def create_patch
|
|
49
|
+
begin
|
|
50
|
+
require 'win32/registry'
|
|
51
|
+
rescue LoadError
|
|
52
|
+
return Rake::Funnel::Support::Patch.new(self)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Rake::Funnel::Support::Patch.new(self) do |p|
|
|
56
|
+
resets = []
|
|
57
|
+
|
|
58
|
+
p.setup do
|
|
59
|
+
resets = KEYS.map do |key|
|
|
60
|
+
root.create(key) do |r|
|
|
61
|
+
begin
|
|
62
|
+
r[VERSION_VALUE]
|
|
63
|
+
|
|
64
|
+
delete_version = Proc.new {}
|
|
65
|
+
rescue Win32::Registry::Error
|
|
66
|
+
r[VERSION_VALUE] = FAKE_VERSION
|
|
67
|
+
|
|
68
|
+
delete_version = delete_value(r, VERSION_VALUE)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
delete_key(r) || delete_version
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
p.reset do
|
|
77
|
+
resets.compact.each do |reset|
|
|
78
|
+
reset.call
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'rake/tasklib'
|
|
2
|
+
|
|
3
|
+
module Rake::Funnel::Tasks
|
|
4
|
+
class NUnit < Rake::TaskLib
|
|
5
|
+
attr_accessor :name, :files, :args
|
|
6
|
+
|
|
7
|
+
def initialize(name = :test)
|
|
8
|
+
@name = name
|
|
9
|
+
@args = {}
|
|
10
|
+
@files = %w(build/specs/**/*.dll build/specs/**/*.exe)
|
|
11
|
+
|
|
12
|
+
yield self if block_given?
|
|
13
|
+
define
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def nunit
|
|
17
|
+
@_nunit || 'nunit-console.exe'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def nunit=(value)
|
|
21
|
+
@_nunit = value
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
def define
|
|
26
|
+
desc "Test #{test_assemblies.all_or_default.join(', ')}"
|
|
27
|
+
task name do
|
|
28
|
+
Rake::Funnel::Integration::TeamCity::NUnitPlugin.setup(nunit)
|
|
29
|
+
|
|
30
|
+
cmd = [
|
|
31
|
+
*Rake::Funnel::Support::Mono.invocation(nunit),
|
|
32
|
+
*test_assemblies.all,
|
|
33
|
+
*Rake::Funnel::Support::Mapper.new(:NUnit).map(args)
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
sh(*cmd)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_assemblies
|
|
43
|
+
Rake::Funnel::Support::Finder.new(files, self, 'No test assemblies found.')
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'rake/tasklib'
|
|
2
|
+
|
|
3
|
+
module Rake::Funnel::Tasks
|
|
4
|
+
class Paket < Rake::TaskLib
|
|
5
|
+
attr_accessor :name, :paket, :paket_args, :bootstrapper, :bootstrapper_args
|
|
6
|
+
|
|
7
|
+
def initialize(name = :paket)
|
|
8
|
+
@name = name
|
|
9
|
+
|
|
10
|
+
@paket = File.join('.paket', 'paket.exe')
|
|
11
|
+
@paket_args = 'restore'
|
|
12
|
+
|
|
13
|
+
@bootstrapper = File.join('.paket', 'paket.bootstrapper.exe')
|
|
14
|
+
@bootstrapper_args = nil
|
|
15
|
+
|
|
16
|
+
yield self if block_given?
|
|
17
|
+
define
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
def define
|
|
22
|
+
desc "#{paket_cmd.join(' ')} (optionally #{bootstrapper_cmd.join(' ')})"
|
|
23
|
+
task name do
|
|
24
|
+
sh(*bootstrapper_cmd) unless File.exist?(paket)
|
|
25
|
+
sh(*paket_cmd)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def bootstrapper_cmd
|
|
32
|
+
Rake::Funnel::Support::Mono.invocation(bootstrapper, bootstrapper_args)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def paket_cmd
|
|
36
|
+
Rake::Funnel::Support::Mono.invocation(paket, paket_args)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'rake/clean'
|
|
2
|
+
require 'rake/tasklib'
|
|
3
|
+
|
|
4
|
+
module Rake::Funnel::Tasks
|
|
5
|
+
class QuickTemplate < Rake::TaskLib
|
|
6
|
+
attr_accessor :name, :search_pattern, :context
|
|
7
|
+
|
|
8
|
+
def initialize(name = :template)
|
|
9
|
+
@name = name
|
|
10
|
+
|
|
11
|
+
@search_pattern = %w(**/*.template)
|
|
12
|
+
@context = binding
|
|
13
|
+
|
|
14
|
+
yield self if block_given?
|
|
15
|
+
define
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
def define
|
|
20
|
+
results = templates.all_or_default.map { |t| result_filename(t) }
|
|
21
|
+
CLEAN.include(*results)
|
|
22
|
+
|
|
23
|
+
desc "Generate #{templates.all_or_default.join(', ')}"
|
|
24
|
+
task name do
|
|
25
|
+
templates.all_or_default.each do |template|
|
|
26
|
+
target = result_filename(template)
|
|
27
|
+
Rake.rake_output_message "Creating file #{target}"
|
|
28
|
+
|
|
29
|
+
content = Rake::Funnel::Support::TemplateEngine.render(File.read(template), template, context)
|
|
30
|
+
File.write(target, content)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def templates
|
|
38
|
+
Rake::Funnel::Support::Finder.new(search_pattern, self, 'No templates found.')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def result_filename(template)
|
|
42
|
+
template.ext
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'rake/tasklib'
|
|
2
|
+
|
|
3
|
+
Dir["#{File.dirname(__FILE__)}/side_by_side_specs_support/*.rb"].each do |path|
|
|
4
|
+
require path
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module Rake::Funnel::Tasks
|
|
8
|
+
class SideBySideSpecs < Rake::TaskLib
|
|
9
|
+
attr_accessor :name, :projects, :references, :specs, :enabled
|
|
10
|
+
|
|
11
|
+
def initialize(name = :compile)
|
|
12
|
+
@name = name
|
|
13
|
+
|
|
14
|
+
@projects = %w(**/*.csproj **/*.vbproj **/*.fsproj)
|
|
15
|
+
@references = []
|
|
16
|
+
@specs = %w(*Specs.cs **/*Specs.cs *Tests.cs **/*Tests.cs)
|
|
17
|
+
@enabled = false
|
|
18
|
+
|
|
19
|
+
yield self if block_given?
|
|
20
|
+
define
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
def define
|
|
25
|
+
task name do
|
|
26
|
+
next unless enabled
|
|
27
|
+
SideBySideSpecsSupport::Remover.remove({ projects: projects, references: references, specs: specs })
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'rexml/document'
|
|
2
|
+
|
|
3
|
+
module Rake::Funnel::Tasks::SideBySideSpecsSupport
|
|
4
|
+
class Remover
|
|
5
|
+
class << self
|
|
6
|
+
DEFAULTS = {
|
|
7
|
+
projects: [],
|
|
8
|
+
references: [],
|
|
9
|
+
specs: []
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def remove(args = {})
|
|
13
|
+
args = DEFAULTS.merge(args)
|
|
14
|
+
|
|
15
|
+
projects(args).each do |project|
|
|
16
|
+
xml = REXML::Document.new(File.read(project), { attribute_quote: :quote })
|
|
17
|
+
|
|
18
|
+
removed = remove_references(args, xml) + remove_specs(args, xml)
|
|
19
|
+
|
|
20
|
+
write_xml(project, xml) if removed.flatten.any?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
delete_specs(args)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def write_xml(project, xml)
|
|
28
|
+
File.open(project, 'w+') do |file|
|
|
29
|
+
xml.write(output: file, ie_hack: true)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def delete_specs(args)
|
|
34
|
+
Dir[*args[:specs]].uniq.each do |spec|
|
|
35
|
+
RakeFileUtils.rm(spec)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def projects(args)
|
|
40
|
+
Dir[*args[:projects]]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def list(args)
|
|
44
|
+
([] << args).flatten
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def remove_references(args, xml)
|
|
48
|
+
list(args[:references]).map do |ref|
|
|
49
|
+
query = "/Project//Reference[starts-with(lower-case(@Include), '#{ref.downcase}')]"
|
|
50
|
+
xml.elements.delete_all(query)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def remove_specs(args, xml)
|
|
55
|
+
list(args[:specs]).map do |glob|
|
|
56
|
+
query = "/Project//Compile[matches(lower-case(@Include), '#{glob}')]"
|
|
57
|
+
xml.elements.delete_all(query)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/tasklib'
|
|
3
|
+
|
|
4
|
+
Dir["#{File.dirname(__FILE__)}/timing_support/*.rb"].each do |path|
|
|
5
|
+
require path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Rake::Funnel::Tasks
|
|
9
|
+
class Timing < Rake::TaskLib
|
|
10
|
+
attr_accessor :name
|
|
11
|
+
attr_reader :stats
|
|
12
|
+
|
|
13
|
+
def initialize(name = :timing)
|
|
14
|
+
@name = name
|
|
15
|
+
@stats = TimingSupport::Statistics.new
|
|
16
|
+
|
|
17
|
+
yield self if block_given?
|
|
18
|
+
|
|
19
|
+
define
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reset!
|
|
23
|
+
patches.each { |p| p.revert! }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def define
|
|
28
|
+
patches.each { |p| p.apply! }
|
|
29
|
+
|
|
30
|
+
task @name, :failed do |task, args|
|
|
31
|
+
TimingSupport::Report.new(@stats, args).render
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
timing_task = Rake.application.current_scope.path_with_task_name(@name)
|
|
35
|
+
Rake.application.top_level_tasks.push(timing_task)
|
|
36
|
+
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def patches
|
|
41
|
+
@patches ||= create_patches
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def create_patches
|
|
45
|
+
report = Rake::Funnel::Support::Patch.new do |p|
|
|
46
|
+
report_invoker = -> (opts) { TimingSupport::Report.new(@stats, opts).render }
|
|
47
|
+
|
|
48
|
+
p.setup do
|
|
49
|
+
Rake::Application.class_eval do
|
|
50
|
+
orig_display_error_message = instance_method(:display_error_message)
|
|
51
|
+
|
|
52
|
+
define_method(:display_error_message) do |ex|
|
|
53
|
+
orig_display_error_message.bind(self).call(ex)
|
|
54
|
+
|
|
55
|
+
report_invoker.call(failed: true)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
orig_display_error_message
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
p.reset do |memo|
|
|
63
|
+
Rake::Application.class_eval do
|
|
64
|
+
define_method(:display_error_message) do |ex|
|
|
65
|
+
memo.bind(self).call(ex)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
benchmark = Rake::Funnel::Support::Patch.new do |p|
|
|
72
|
+
benchmark_invoker = -> (task, &block) { @stats.benchmark(task, &block) }
|
|
73
|
+
|
|
74
|
+
p.setup do
|
|
75
|
+
Rake::Task.class_eval do
|
|
76
|
+
orig_execute = instance_method(:execute)
|
|
77
|
+
|
|
78
|
+
define_method(:execute) do |args|
|
|
79
|
+
benchmark_invoker.call(self) do
|
|
80
|
+
orig_execute.bind(self).call(args)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
orig_execute
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
p.reset do |memo|
|
|
89
|
+
Rake::Task.class_eval do
|
|
90
|
+
define_method(:execute) do |ex|
|
|
91
|
+
memo.bind(self).call(ex)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
[report, benchmark]
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'smart_colored/extend'
|
|
2
|
+
|
|
3
|
+
module Rake::Funnel::Tasks::TimingSupport
|
|
4
|
+
class Report
|
|
5
|
+
class Column
|
|
6
|
+
attr_reader :header
|
|
7
|
+
|
|
8
|
+
def initialize(stats: [], header: '', accessor: -> (_) { '' })
|
|
9
|
+
@stats = stats
|
|
10
|
+
@header = header
|
|
11
|
+
@accessor = accessor
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def width
|
|
15
|
+
longest_value = @stats.map { |s| @accessor.call(s) }.max_by { |m| m.length } || ''
|
|
16
|
+
width = longest_value.length
|
|
17
|
+
width = @header.length if width < @header.length
|
|
18
|
+
width
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def format_header
|
|
22
|
+
@header.ljust(width)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def format_value(value)
|
|
26
|
+
@accessor.call(value).ljust(width)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
SPACE = 3
|
|
31
|
+
HEADER_WIDTH = 70
|
|
32
|
+
|
|
33
|
+
def initialize(stats, opts = {})
|
|
34
|
+
@stats = stats
|
|
35
|
+
@opts = opts
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def render
|
|
39
|
+
header
|
|
40
|
+
rows
|
|
41
|
+
footer
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def columns
|
|
45
|
+
@columns ||= ([
|
|
46
|
+
Column.new(stats: @stats, header: 'Target', accessor: -> (timing) { timing[:task].name }),
|
|
47
|
+
Column.new(stats: @stats, header: 'Duration', accessor: -> (timing) { format(timing[:time]) })
|
|
48
|
+
])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
def header
|
|
53
|
+
puts '-' * HEADER_WIDTH
|
|
54
|
+
puts 'Build time report'
|
|
55
|
+
puts '-' * HEADER_WIDTH
|
|
56
|
+
|
|
57
|
+
puts columns.map { |c| c.format_header }.join(' ' * SPACE)
|
|
58
|
+
puts columns.map { |c| c.format_header.gsub(/./, '-') }.join(' ' * SPACE)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def rows
|
|
62
|
+
@stats.each do |timing|
|
|
63
|
+
puts columns.map { |c| c.format_value(timing) }.join(' ' * SPACE)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def footer
|
|
68
|
+
puts '-' * HEADER_WIDTH
|
|
69
|
+
puts 'Total'.ljust(columns[0].width) + ' ' * SPACE + format(Time.now - @stats.started_at)
|
|
70
|
+
status_message
|
|
71
|
+
puts '-' * HEADER_WIDTH
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def format(seconds)
|
|
75
|
+
Time.at(seconds).utc.strftime('%H:%M:%S')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def status_message
|
|
79
|
+
status = @opts[:failed] ? 'Failed' : 'OK'
|
|
80
|
+
status = 'Status'.ljust(columns[0].width) + ' ' * SPACE + status
|
|
81
|
+
|
|
82
|
+
if @opts[:failed]
|
|
83
|
+
$stderr.puts status.bold.red
|
|
84
|
+
else
|
|
85
|
+
$stdout.puts status.bold.green
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Rake::Funnel::Tasks::TimingSupport
|
|
2
|
+
class Statistics
|
|
3
|
+
include Enumerable
|
|
4
|
+
|
|
5
|
+
attr_reader :started_at
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@stats = []
|
|
9
|
+
@started_at = Time.now
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def each(&block)
|
|
13
|
+
@stats.each(&block)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def benchmark(task)
|
|
17
|
+
t0 = Time.now
|
|
18
|
+
begin
|
|
19
|
+
yield if block_given?
|
|
20
|
+
ensure
|
|
21
|
+
t1 = Time.now
|
|
22
|
+
@stats << { task: task, time: t1 - t0 }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|