ironbuildrake 0.1.1-ironruby
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/README +0 -0
- data/Rakefile +74 -0
- data/VERSION +1 -0
- data/ironbuildrake.gemspec +56 -0
- data/lib/Microsoft.Build.Tasks.rb +6 -0
- data/lib/assembly_loader.rb +23 -0
- data/lib/build_engine.rb +105 -0
- data/lib/namespace_node.rb +49 -0
- data/lib/task_item.rb +56 -0
- data/lib/task_library.rb +124 -0
- data/lib/tasks_file.rb +104 -0
- data/test/helper.rb +8 -0
- data/test/tests_namespace_node.rb +46 -0
- data/test/tests_other_libraries.rb +53 -0
- data/test/tests_targets_file.rb +210 -0
- data/test/tests_task_library.rb +94 -0
- data/test/tests_tasks.rb +127 -0
- metadata +64 -0
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
$: << "lib"
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require "build_engine.rb"
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gem|
|
10
|
+
gem.name = "ironbuildrake"
|
11
|
+
gem.summary = %Q{Adds support for using msbuild tasks in ironruby with rake }
|
12
|
+
gem.description = %Q{}
|
13
|
+
gem.email = "brunomlopes@gmail.com"
|
14
|
+
gem.homepage = "http://github.com/brunomlopes/ironbuildrake"
|
15
|
+
gem.authors = ["Bruno Lopes"]
|
16
|
+
gem.files = FileList["[A-Z]*", "{lib, test}/**/*" ]
|
17
|
+
gem.platform = "ironruby"
|
18
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/test_*.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
require 'rcov/rcovtask'
|
34
|
+
Rcov::RcovTask.new do |test|
|
35
|
+
test.libs << 'test'
|
36
|
+
test.pattern = 'test/**/test_*.rb'
|
37
|
+
test.verbose = true
|
38
|
+
end
|
39
|
+
rescue LoadError
|
40
|
+
task :rcov do
|
41
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
task :test => :check_dependencies
|
46
|
+
|
47
|
+
task :default => :test
|
48
|
+
|
49
|
+
require 'rake/rdoctask'
|
50
|
+
Rake::RDocTask.new do |rdoc|
|
51
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
52
|
+
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
54
|
+
rdoc.title = "ironbuildrake #{version}"
|
55
|
+
rdoc.rdoc_files.include('README*')
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
+
end
|
58
|
+
|
59
|
+
# task :default => [:test_units]
|
60
|
+
|
61
|
+
desc "this is just a quick smoke test"
|
62
|
+
task :test do
|
63
|
+
msbuild = tasks_from_module(Microsoft::Build::Tasks)
|
64
|
+
msbuild.Message :text => "This is a text message"
|
65
|
+
msbuild.Warning :text => "This is a warning"
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "Run unit tests"
|
69
|
+
Rake::TestTask.new("test_units") do |t|
|
70
|
+
t.libs << "test"
|
71
|
+
t.pattern = 'test/tests_*.rb'
|
72
|
+
t.verbose = true
|
73
|
+
t.warning = true
|
74
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ironbuildrake}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
s.platform = %q{ironruby}
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.authors = ["Bruno Lopes"]
|
13
|
+
s.date = %q{2009-12-26}
|
14
|
+
s.description = %q{}
|
15
|
+
s.email = %q{brunomlopes@gmail.com}
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"README"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"README",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"ironbuildrake.gemspec",
|
24
|
+
"lib/Microsoft.Build.Tasks.rb",
|
25
|
+
"lib/assembly_loader.rb",
|
26
|
+
"lib/build_engine.rb",
|
27
|
+
"lib/namespace_node.rb",
|
28
|
+
"lib/task_item.rb",
|
29
|
+
"lib/task_library.rb",
|
30
|
+
"lib/tasks_file.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/brunomlopes/ironbuildrake}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.5}
|
36
|
+
s.summary = %q{Adds support for using msbuild tasks in ironruby with rake}
|
37
|
+
s.test_files = [
|
38
|
+
"test/helper.rb",
|
39
|
+
"test/tests_namespace_node.rb",
|
40
|
+
"test/tests_other_libraries.rb",
|
41
|
+
"test/tests_targets_file.rb",
|
42
|
+
"test/tests_tasks.rb",
|
43
|
+
"test/tests_task_library.rb"
|
44
|
+
]
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
|
+
else
|
52
|
+
end
|
53
|
+
else
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require "Microsoft.Build.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
|
2
|
+
require "Microsoft.Build.Utilities, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
|
3
|
+
require "Microsoft.Build.Framework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
|
4
|
+
|
5
|
+
#require 'Microsoft.Build.Framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
|
6
|
+
#require 'Microsoft.Build.Utilities.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
class AssemblyLoader
|
4
|
+
@@assembly_paths = Set.new
|
5
|
+
|
6
|
+
def self.add_path(path)
|
7
|
+
raise Exception.new("Path cannot be nil") if path == nil
|
8
|
+
@@assembly_paths.add(path) if path != nil
|
9
|
+
end
|
10
|
+
|
11
|
+
System::AppDomain.current_domain.assembly_resolve do |sender, event|
|
12
|
+
found_path = nil
|
13
|
+
@@assembly_paths.each do |path|
|
14
|
+
assembly_path = System::IO::Path.get_full_path(System::IO::Path.combine(path,event.name))
|
15
|
+
if System::IO::File.exists(assembly_path)
|
16
|
+
found_path = assembly_path
|
17
|
+
break
|
18
|
+
end
|
19
|
+
end
|
20
|
+
throw System::IO::FileNotFoundException.new(event.name) unless found_path
|
21
|
+
System::Reflection::Assembly.LoadFile(found_path)
|
22
|
+
end
|
23
|
+
end
|
data/lib/build_engine.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'Microsoft.Build.Tasks'
|
2
|
+
require 'logger'
|
3
|
+
require 'tasks_file'
|
4
|
+
require 'task_library'
|
5
|
+
|
6
|
+
class RubyBuildEngine
|
7
|
+
include Microsoft::Build::Framework::IBuildEngine
|
8
|
+
# include Microsoft::Build::Framework::IBuildEngine2
|
9
|
+
attr_reader :column_number_of_task_node, :continue_on_error, :line_number_of_task_node,
|
10
|
+
:project_file_of_task_node, :is_running_multiple_nodes
|
11
|
+
|
12
|
+
def initialize(logger)
|
13
|
+
@logger = logger
|
14
|
+
@column_number_of_task_node = 1
|
15
|
+
@continue_on_error = true
|
16
|
+
@line_number_of_task_node = 2
|
17
|
+
@project_file_of_task_node = "project.file"
|
18
|
+
@is_running_multiple_nodes = false
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
def build_project_file(project_file_name, # string
|
24
|
+
target_names, # string[]
|
25
|
+
global_properties, # IDictionary
|
26
|
+
target_outputs, #IDictionary
|
27
|
+
tools_version #string
|
28
|
+
)
|
29
|
+
return true
|
30
|
+
end
|
31
|
+
|
32
|
+
def BuildProjectFilesInParallel(project_file_names, #string[]
|
33
|
+
target_names, #string[],
|
34
|
+
global_properties, #IDictionary[]
|
35
|
+
target_outputs_per_project, #IDictionary[]
|
36
|
+
tools_version, #string[]
|
37
|
+
use_results_cache, #bool
|
38
|
+
unload_projects_on_completion) #bool
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_project_file(project_file_name, # string
|
43
|
+
target_names, # string[]
|
44
|
+
global_properties, # IDictionary
|
45
|
+
target_outputs #IDictionary
|
46
|
+
)
|
47
|
+
return true
|
48
|
+
end
|
49
|
+
|
50
|
+
def log_event(e)
|
51
|
+
@logger.debug("#{e.Timestamp}:#{e.ThreadId}:#{e.SenderName}:#{e.Message}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def log_custom_event(e) # CustomBuildEventArgs
|
55
|
+
log_event(e)
|
56
|
+
@logger.debug("Custom event: " + e.to_s)
|
57
|
+
end
|
58
|
+
|
59
|
+
def log_error_event(e) #BuildErrorEventArgs
|
60
|
+
log_event(e)
|
61
|
+
@logger.error("#{e.Code}:#{e.ColumnNumber}:#{e.EndColumnNumber}:#{e.EndLineNumber}:#{e.File}:#{e.LineNumber}:#{e.Subcategory}")
|
62
|
+
end
|
63
|
+
|
64
|
+
def log_message_event(e) #BuildMessageEventArgs
|
65
|
+
log_event(e)
|
66
|
+
# TODO: implement importance (dunno how)
|
67
|
+
@logger.info(e.Message)
|
68
|
+
end
|
69
|
+
|
70
|
+
def log_warning_event(e) #BuildWarningEventArgs
|
71
|
+
log_event(e)
|
72
|
+
@logger.warn(e.Message)
|
73
|
+
@logger.debug("#{e.Code}:#{e.ColumnNumber}:#{e.EndColumnNumber}:#{e.EndLineNumber}:#{e.File}:#{e.LineNumber}:#{e.Subcategory}")
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
logger = Logger.new(STDOUT)
|
79
|
+
logger.level = Logger::INFO
|
80
|
+
$build_engine = RubyBuildEngine.new(logger)
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
def tasks_from_module(mod)
|
85
|
+
TaskLibrary.from_modules($build_engine, mod)
|
86
|
+
end
|
87
|
+
|
88
|
+
def tasks_from_file(tasks_file)
|
89
|
+
TaskLibrary.from_tasks_file($build_engine, tasks_file)
|
90
|
+
end
|
91
|
+
|
92
|
+
def tasks_from_msbuild_2_0()
|
93
|
+
load_assembly 'Microsoft.Build.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
|
94
|
+
#directory = System::Runtime::InteropServices::RuntimeEnvironment.get_runtime_directory
|
95
|
+
#file_name = "Microsoft.Common.Tasks"
|
96
|
+
#full_path = System::IO::Path.combine(directory, file_name)
|
97
|
+
return TaskLibrary.from_modules($build_engine, Microsoft::Build::Tasks)
|
98
|
+
end
|
99
|
+
|
100
|
+
def tasks_from_msbuild_3_5()
|
101
|
+
directory = System::Environment.expand_environment_variables('%WINDIR%\Microsoft.NET\Framework\v3.5')
|
102
|
+
file_name = "Microsoft.Common.Tasks"
|
103
|
+
full_path = System::IO::Path.combine(directory, file_name)
|
104
|
+
return TaskLibrary.from_tasks_file($build_engine, full_path)
|
105
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class NamespaceNode
|
2
|
+
attr_reader :name, :children
|
3
|
+
def initialize(name)
|
4
|
+
@name = name
|
5
|
+
@children = { }
|
6
|
+
@objects = { }
|
7
|
+
end
|
8
|
+
|
9
|
+
def << (name)
|
10
|
+
add_child(name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_child(name)
|
14
|
+
if @objects.has_key? name
|
15
|
+
raise Exception.new("Node #{@name} already has object with name #{name}")
|
16
|
+
end
|
17
|
+
if not @children.has_key? name
|
18
|
+
@children[name] = NamespaceNode.new(name)
|
19
|
+
self.metaclass.send :define_method, name do
|
20
|
+
@children[name]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
@children[name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_object(name, object, *namespaces)
|
27
|
+
raise Exception.new("Node #{@name} already has child node with name #{name}") if @children.has_key? name
|
28
|
+
raise Exception.new("Node #{@name} already has object with name #{name}") if @objects.has_key? name
|
29
|
+
|
30
|
+
if namespaces.length > 0
|
31
|
+
next_namespace = namespaces.shift.to_s
|
32
|
+
raise Exception.new("No namespace with name #{next_namespace} found") if not @children.has_key?(next_namespace)
|
33
|
+
@children[next_namespace].add_object(name, object, *namespaces)
|
34
|
+
else
|
35
|
+
@objects[name] = object
|
36
|
+
self.metaclass.send :define_method, name do
|
37
|
+
@objects[name]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def metaclass
|
45
|
+
class << self
|
46
|
+
self
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/task_item.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'Microsoft.Build.Tasks'
|
2
|
+
|
3
|
+
class TaskItem
|
4
|
+
include Microsoft::Build::Framework::ITaskItem
|
5
|
+
attr_accessor :item_spec
|
6
|
+
|
7
|
+
def initialize(str)
|
8
|
+
@item_spec = str
|
9
|
+
@metadata = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def metadata_count
|
13
|
+
return @metadata.length
|
14
|
+
end
|
15
|
+
|
16
|
+
def metadata_names
|
17
|
+
return @metadata.keys
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
return @item_spec
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_metadata(metadata_name) # string => string
|
25
|
+
if @metadata.has_key?(metadata_name)
|
26
|
+
return @metadata[metadata_name]
|
27
|
+
else
|
28
|
+
return ""
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_metadata(metadata_name, metadata_value) # string,string => void
|
33
|
+
@metadata[metadata_name] = metadata_value
|
34
|
+
end
|
35
|
+
|
36
|
+
def remove_metadata(metadata_name) # string => void
|
37
|
+
@metadata.delete(metadata_name) if @metadata.has_key?(metadata_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def copy_metadata_to(destination_item) #itaskitem => void
|
41
|
+
@metadata.each_pair do |key, value|
|
42
|
+
original_metadata = destination_item.get_metadata(key)
|
43
|
+
if original_metadata == nil or original_metadata == ""
|
44
|
+
destination_item.set_metadata(key, value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
original_item_spec = destination_item.get_metadata("OriginalItemSpec")
|
48
|
+
if original_item_spec == nil or original_item_spec == ""
|
49
|
+
destination_item.set_metadata("OriginalItemSpec", @item_spec)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def clone_custom_metadata()# void => IDictionary
|
54
|
+
return Hash.new().merge(@metadata)
|
55
|
+
end
|
56
|
+
end
|
data/lib/task_library.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'task_item'
|
2
|
+
require 'assembly_loader'
|
3
|
+
require 'namespace_node'
|
4
|
+
|
5
|
+
class TaskLibrary
|
6
|
+
attr_reader :tasks
|
7
|
+
|
8
|
+
def self.from_modules(build_engine, *modules)
|
9
|
+
tasks = self.tasks_in_modules(modules)
|
10
|
+
return TaskLibrary.new(build_engine, tasks)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_tasks_file(build_engine, task_file_path)
|
14
|
+
targets = TasksFile.from_file(task_file_path)
|
15
|
+
targets.load_assemblies()
|
16
|
+
|
17
|
+
tasks = targets.task_class_names.map do |class_name|
|
18
|
+
begin
|
19
|
+
ruby_class_name = class_name.gsub(/\./,"::")
|
20
|
+
eval(ruby_class_name)
|
21
|
+
rescue NameError
|
22
|
+
puts "Error loading task class #{ruby_class_name}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
tasks = tasks.delete_if{ |task| task == nil}
|
26
|
+
return TaskLibrary.new(build_engine, tasks)
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(build_engine, tasks)
|
30
|
+
@root_namespace = NamespaceNode.new("")
|
31
|
+
@tasks = tasks
|
32
|
+
namespaces = Set.new(@tasks.map{ |cls| cls.to_clr_type.namespace })
|
33
|
+
|
34
|
+
namespaces.each do |namespace|
|
35
|
+
next if namespace.strip.size == 0
|
36
|
+
|
37
|
+
split_namespaces = String.new(namespace).split(".")
|
38
|
+
define_root_namespace_method(split_namespaces[0])
|
39
|
+
|
40
|
+
node = @root_namespace
|
41
|
+
while split_namespaces.size > 0
|
42
|
+
node = node.add_child(split_namespaces.shift)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@tasks.each do |cls|
|
47
|
+
method_name = cls.to_clr_type.name.to_sym
|
48
|
+
task_namespace = cls.to_clr_type.namespace.split(".")
|
49
|
+
define_execute_method(method_name, build_engine, cls)
|
50
|
+
@root_namespace.add_object(method_name, lambda {|args| execute_method(build_engine, cls, args) }, *task_namespace)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def define_root_namespace_method(namespace)
|
55
|
+
self.metaclass.send :define_method, namespace do
|
56
|
+
@root_namespace.send namespace
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def define_execute_method(method_name, build_engine, cls)
|
61
|
+
self.metaclass.send :define_method, method_name do |args|
|
62
|
+
execute_method(build_engine, cls, args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def execute_method(build_engine, cls, args)
|
67
|
+
args ||= {}
|
68
|
+
instance = cls.new
|
69
|
+
instance.BuildEngine = build_engine
|
70
|
+
|
71
|
+
properties = instance.class.to_clr_type.get_properties
|
72
|
+
|
73
|
+
args.each_pair do |k, v|
|
74
|
+
property = properties.find {|prop| prop.name.downcase == k.to_s.downcase}
|
75
|
+
if property == nil
|
76
|
+
return
|
77
|
+
end
|
78
|
+
value = value_for_property(property, v)
|
79
|
+
|
80
|
+
property.set_value(instance, value, nil)
|
81
|
+
end
|
82
|
+
instance.Execute
|
83
|
+
end
|
84
|
+
|
85
|
+
def value_for_property(property, original_value)
|
86
|
+
itaskitem = Microsoft::Build::Framework::ITaskItem
|
87
|
+
value = original_value
|
88
|
+
if value.kind_of?(Array)
|
89
|
+
value = System::Array.of(itaskitem).new(original_value.map{|item| TaskItem.new(item)})
|
90
|
+
elsif value.kind_of?(String)
|
91
|
+
return_type_name = property.get_get_method.return_type.full_name
|
92
|
+
if return_type_name == "System.String"
|
93
|
+
value = value.to_clr_string
|
94
|
+
else
|
95
|
+
value = System::Array.of(itaskitem).new([value].map{|item| TaskItem.new(item)})
|
96
|
+
end
|
97
|
+
end
|
98
|
+
return value
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.tasks_in_modules(modules)
|
102
|
+
itask_interface = Microsoft::Build::Framework::ITask.to_clr_type
|
103
|
+
tasks = []
|
104
|
+
modules.each do |mod|
|
105
|
+
classes = mod.constants.map { |c| mod.class_eval(c) }
|
106
|
+
classes = classes.select do |cls|
|
107
|
+
if !cls.respond_to?(:to_clr_type) || !cls.to_clr_type.respond_to?(:get_interfaces)
|
108
|
+
interfaces = []
|
109
|
+
else
|
110
|
+
interfaces = cls.to_clr_type.get_interfaces
|
111
|
+
end
|
112
|
+
interfaces.include?(itask_interface)
|
113
|
+
end
|
114
|
+
tasks.concat(classes)
|
115
|
+
end
|
116
|
+
return tasks
|
117
|
+
end
|
118
|
+
|
119
|
+
def metaclass
|
120
|
+
class << self
|
121
|
+
self
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/tasks_file.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require "rexml/document"
|
2
|
+
require "assembly_loader"
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
include REXML
|
6
|
+
|
7
|
+
class TasksFile
|
8
|
+
attr_reader :task_infos, :assembly_file_names, :assembly_names, :task_class_names
|
9
|
+
|
10
|
+
def self.from_xml(xml, file_path = nil)
|
11
|
+
document = Document.new(xml)
|
12
|
+
properties = PropertyGroups.from_xml(xml)
|
13
|
+
|
14
|
+
tasks = document.elements.to_a("Project/UsingTask").map do |element|
|
15
|
+
assembly_file = properties.replace_variables_in(element.attributes["AssemblyFile"])
|
16
|
+
assembly_name = properties.replace_variables_in(element.attributes["AssemblyName"])
|
17
|
+
task_name = properties.replace_variables_in(element.attributes["TaskName"])
|
18
|
+
TaskInfo.new(task_name, assembly_file, assembly_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
return TasksFile.new(tasks, file_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_file(file_path)
|
25
|
+
return self.from_xml(File.read(file_path), file_path)
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(tasks, file_path = nil)
|
29
|
+
@task_infos = tasks
|
30
|
+
@assembly_file_names = Set.new(@task_infos.map {|task| task.assembly_file }).delete(nil)
|
31
|
+
@assembly_names = Set.new(@task_infos.map {|task| task.assembly_name }).delete(nil)
|
32
|
+
@task_class_names = Set.new(@task_infos.map {|task| task.task_name}).delete(nil)
|
33
|
+
@file_path = file_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_assemblies()
|
37
|
+
AssemblyLoader.add_path(System::IO::Path.get_directory_name(@file_path)) if @file_path != nil
|
38
|
+
|
39
|
+
@assembly_file_names.each do |assembly_file_name|
|
40
|
+
task_file_directory = System::IO::Path.get_directory_name(assembly_file_name)
|
41
|
+
AssemblyLoader.add_path(task_file_directory)
|
42
|
+
|
43
|
+
assembly_file = System::IO::Path.get_file_name(assembly_file_name)
|
44
|
+
load_assembly(assembly_file)
|
45
|
+
end
|
46
|
+
|
47
|
+
@assembly_names.each do |assembly_name|
|
48
|
+
load_assembly(assembly_name)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class TaskInfo
|
54
|
+
attr_reader :task_name, :assembly_file, :assembly_name
|
55
|
+
|
56
|
+
def initialize(task_name, assembly_file, assembly_name)
|
57
|
+
@task_name = task_name
|
58
|
+
while assembly_file =~ /\\\\/
|
59
|
+
assembly_file.gsub!(/\\\\/,"\\")
|
60
|
+
end
|
61
|
+
@assembly_file = assembly_file
|
62
|
+
@assembly_name = assembly_name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class PropertyGroups
|
67
|
+
attr_reader :elements
|
68
|
+
|
69
|
+
def self.from_xml(xml)
|
70
|
+
document = Document.new(xml)
|
71
|
+
properties = Hash.new
|
72
|
+
document.elements.each("Project/PropertyGroup/*") do |element|
|
73
|
+
properties[element.name] = element.text.strip
|
74
|
+
end
|
75
|
+
return PropertyGroups.new(properties)
|
76
|
+
end
|
77
|
+
|
78
|
+
def initialize(elements)
|
79
|
+
@variable_regexp = /\$\([\w]+\)/
|
80
|
+
@elements = elements
|
81
|
+
elements.each_pair do |key, value|
|
82
|
+
PropertyGroups.class_eval do
|
83
|
+
define_method key.to_sym do ||
|
84
|
+
return replace_variables_in(value)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def replace_variables_in(str)
|
91
|
+
replaced_value = str
|
92
|
+
while @variable_regexp.match(replaced_value)
|
93
|
+
match = @variable_regexp.match(replaced_value)
|
94
|
+
full_var = match[0]
|
95
|
+
var_name = full_var[2..-2]
|
96
|
+
if elements.key? var_name
|
97
|
+
replaced_value = replaced_value.sub(full_var, @elements[var_name])
|
98
|
+
else
|
99
|
+
replaced_value = replaced_value.sub(full_var, "")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
return replaced_value
|
103
|
+
end
|
104
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'namespace_node'
|
4
|
+
require 'helper'
|
5
|
+
|
6
|
+
class TestNamespaceNodes < Test::Unit::TestCase
|
7
|
+
def test_node_can_add_children
|
8
|
+
node = NamespaceNode.new "root"
|
9
|
+
node << "child"
|
10
|
+
assert_respond_to node, :child
|
11
|
+
assert_equal node.child.name, "child"
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_node_can_add_sub_children
|
15
|
+
node = NamespaceNode.new "root"
|
16
|
+
node << "child" << "subchild"
|
17
|
+
assert_respond_to node, :child
|
18
|
+
assert_respond_to node.child, :subchild
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_name_can_add_object
|
22
|
+
node = NamespaceNode.new "root"
|
23
|
+
obj = Object.new
|
24
|
+
node.add_object("object", obj)
|
25
|
+
assert_respond_to node, :object
|
26
|
+
assert_equal node.object, obj
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_add_task_to_namespace
|
30
|
+
node = NamespaceNode.new "root"
|
31
|
+
node << "child"
|
32
|
+
obj = Object.new
|
33
|
+
node.add_object("object", obj, "child")
|
34
|
+
|
35
|
+
assert_respond_to node.child, :object
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_add_task_to_subnamespace
|
39
|
+
node = NamespaceNode.new "root"
|
40
|
+
node << "child" << "subchild"
|
41
|
+
obj = Object.new
|
42
|
+
node.add_object("object", obj, "child", "subchild")
|
43
|
+
|
44
|
+
assert_respond_to node.child.subchild, :object
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'build_engine'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'mocha'
|
6
|
+
require 'pathname'
|
7
|
+
require 'stringio'
|
8
|
+
require 'helper'
|
9
|
+
|
10
|
+
module TaskLibraryMixin
|
11
|
+
def build_engine
|
12
|
+
@output = StringIO.new
|
13
|
+
@output = STDOUT
|
14
|
+
@output_logger = Logger.new(@output)
|
15
|
+
return RubyBuildEngine.new(@output_logger)
|
16
|
+
end
|
17
|
+
|
18
|
+
def task_library
|
19
|
+
TaskLibrary.from_tasks_file(build_engine, @tasks_file)
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert_has_task (task)
|
23
|
+
assert_respond_to task_library, task
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class MSBuildCommunityTasks < Test::Unit::TestCase
|
28
|
+
include TaskLibraryMixin
|
29
|
+
|
30
|
+
def test_loads_assembly_info_task
|
31
|
+
assert_has_task :AssemblyInfo
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_loads_vss_get_task
|
35
|
+
assert_has_task :VssGet
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup
|
39
|
+
@tasks_file = "test/test-libraries/MSBuildCommunityTasks/MSBuild.Community.Tasks.Targets"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class SBF #< Test::Unit::TestCase
|
44
|
+
include TaskLibraryMixin
|
45
|
+
|
46
|
+
def test_loads_biztak_2002_configure_task
|
47
|
+
assert_has_task :Configure
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup
|
51
|
+
@tasks_file = "test/test-libraries/sbf/Microsoft.Sdc.Common.tasks"
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "tasks_file"
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
class TestTargetsFile < Test::Unit::TestCase
|
6
|
+
def test_tasks
|
7
|
+
text = <<XML
|
8
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
9
|
+
<UsingTask AssemblyFile="Tasks.dll" TaskName="UpdateDependencies" />
|
10
|
+
</Project>
|
11
|
+
XML
|
12
|
+
|
13
|
+
targets = TasksFile.from_xml(text)
|
14
|
+
assert_equal(1, targets.task_infos.size)
|
15
|
+
task = targets.task_infos[0]
|
16
|
+
assert_equal("Tasks.dll", task.assembly_file)
|
17
|
+
assert_equal("UpdateDependencies", task.task_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_assemblies_are_the_same
|
21
|
+
text = <<XML
|
22
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
23
|
+
<UsingTask AssemblyFile="Tasks.dll" TaskName="UpdateDependencies" />
|
24
|
+
<UsingTask AssemblyFile="Tasks.dll" TaskName="OtherTask" />
|
25
|
+
</Project>
|
26
|
+
XML
|
27
|
+
|
28
|
+
targets = TasksFile.from_xml(text)
|
29
|
+
assert_equal(1, targets.assembly_file_names.size)
|
30
|
+
assert(targets.assembly_file_names.include?("Tasks.dll"))
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_assemblies_are_diferent
|
34
|
+
text = <<XML
|
35
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
36
|
+
<UsingTask AssemblyFile="Tasks.dll" TaskName="UpdateDependencies" />
|
37
|
+
<UsingTask AssemblyFile="OtherAssembly.dll" TaskName="OtherTask" />
|
38
|
+
</Project>
|
39
|
+
XML
|
40
|
+
|
41
|
+
targets = TasksFile.from_xml(text)
|
42
|
+
assert_equal(2, targets.assembly_file_names.size)
|
43
|
+
assert(targets.assembly_file_names.include?("Tasks.dll"))
|
44
|
+
assert(targets.assembly_file_names.include?("OtherAssembly.dll"))
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_tasks_from_msbuild_have_correct_assembly_name
|
48
|
+
directory = System::Runtime::InteropServices::RuntimeEnvironment.get_runtime_directory
|
49
|
+
file_name = "Microsoft.Common.Tasks"
|
50
|
+
full_path = System::IO::Path.combine(directory, file_name)
|
51
|
+
targets = TasksFile.from_file(full_path)
|
52
|
+
|
53
|
+
assert_equal(41, targets.task_infos.size)
|
54
|
+
assert_equal(1, targets.assembly_names.size)
|
55
|
+
tasks_assembly_name = "Microsoft.Build.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
|
56
|
+
assert(targets.assembly_names.include?(tasks_assembly_name),
|
57
|
+
" #{targets.assembly_names.to_a} does not include #{tasks_assembly_name}")
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def test_tasks_can_load_msbuild_v3_5_tasks_assembly
|
62
|
+
directory = System::Environment.expand_environment_variables('%WINDIR%\Microsoft.NET\Framework\v3.5')
|
63
|
+
file_name = "Microsoft.Common.Tasks"
|
64
|
+
full_path = System::IO::Path.combine(directory, file_name)
|
65
|
+
targets = TasksFile.from_file(full_path)
|
66
|
+
|
67
|
+
targets.load_assemblies()
|
68
|
+
assert_instance_of(Class, Microsoft::Build::Tasks::AssignProjectConfiguration)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_tasks_with_properties
|
72
|
+
text = <<XML
|
73
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
74
|
+
<PropertyGroup>
|
75
|
+
<property>value</property>
|
76
|
+
</PropertyGroup>
|
77
|
+
<UsingTask AssemblyFile="$(property).Tasks.dll" TaskName="UpdateDependencies" />
|
78
|
+
</Project>
|
79
|
+
XML
|
80
|
+
|
81
|
+
targets = TasksFile.from_xml(text)
|
82
|
+
assert_equal(1, targets.task_infos.size)
|
83
|
+
task = targets.task_infos[0]
|
84
|
+
assert_equal("value.Tasks.dll", task.assembly_file)
|
85
|
+
assert_equal("UpdateDependencies", task.task_name)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_sdc_task_with_properties
|
89
|
+
text = <<XML
|
90
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
91
|
+
<PropertyGroup>
|
92
|
+
<BuildPath Condition="'$(BuildPath)'==''">$(MSBuildProjectDirectory)\\</BuildPath>
|
93
|
+
<TasksPath Condition="Exists('$(BuildPath)\\bin\\Microsoft.Sdc.Tasks.dll')">$(BuildPath)\\bin\\</TasksPath>
|
94
|
+
</PropertyGroup>
|
95
|
+
<UsingTask AssemblyFile="$(TasksPath)Microsoft.Sdc.Tasks.dll" TaskName="Microsoft.Sdc.Tasks.ActiveDirectory.Group.AddUser" />
|
96
|
+
</Project>
|
97
|
+
XML
|
98
|
+
targets = TasksFile.from_xml(text)
|
99
|
+
assert_equal(1, targets.task_infos.size)
|
100
|
+
task = targets.task_infos[0]
|
101
|
+
assert_equal("\\bin\\Microsoft.Sdc.Tasks.dll", task.assembly_file)
|
102
|
+
assert_equal("Microsoft.Sdc.Tasks.ActiveDirectory.Group.AddUser", task.task_name)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class TestTaskInfo < Test::Unit::TestCase
|
107
|
+
def test_task_info_fixes_file_with_two_backslashes
|
108
|
+
task_name = "not relevant"
|
109
|
+
assembly_file = "\\\\bin\\AssemblyFile.dll"
|
110
|
+
assembly_name = "AssemblyFile"
|
111
|
+
task_info = TaskInfo.new(task_name, assembly_file, assembly_name)
|
112
|
+
assert_equal("\\bin\\AssemblyFile.dll", task_info.assembly_file)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_task_info_fixes_file_with_way_too_many_backslashes
|
116
|
+
task_name = "not relevant"
|
117
|
+
assembly_file = "\\subdir\\\\dir\\\\\\bin\\\\\\\\AssemblyFile.dll"
|
118
|
+
assembly_name = "AssemblyFile"
|
119
|
+
task_info = TaskInfo.new(task_name, assembly_file, assembly_name)
|
120
|
+
assert_equal("\\subdir\\dir\\bin\\AssemblyFile.dll", task_info.assembly_file)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class TestPropertyGroupParser < Test::Unit::TestCase
|
125
|
+
def test_simple_property
|
126
|
+
text = <<XML
|
127
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
128
|
+
<PropertyGroup>
|
129
|
+
<propertyName>property value</propertyName>
|
130
|
+
</PropertyGroup>
|
131
|
+
</Project>
|
132
|
+
XML
|
133
|
+
|
134
|
+
properties = PropertyGroups.from_xml(text)
|
135
|
+
assert_equal("property value", properties.propertyName)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_property_defined_in_terms_of_another
|
139
|
+
text = <<XML
|
140
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
141
|
+
<PropertyGroup>
|
142
|
+
<variable>value</variable>
|
143
|
+
<propertyName>property $(variable)</propertyName>
|
144
|
+
</PropertyGroup>
|
145
|
+
</Project>
|
146
|
+
XML
|
147
|
+
|
148
|
+
properties = PropertyGroups.from_xml(text)
|
149
|
+
assert_equal("property value", properties.propertyName)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_property_defined_in_terms_of_another_two
|
153
|
+
text = <<XML
|
154
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
155
|
+
<PropertyGroup>
|
156
|
+
<first>value</first>
|
157
|
+
<second>$(first)</second>
|
158
|
+
<propertyName>property $(second)</propertyName>
|
159
|
+
</PropertyGroup>
|
160
|
+
</Project>
|
161
|
+
XML
|
162
|
+
|
163
|
+
properties = PropertyGroups.from_xml(text)
|
164
|
+
assert_equal("property value", properties.propertyName)
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_property_defined_in_terms_of_another_two_jumbled
|
168
|
+
text = <<XML
|
169
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
170
|
+
<PropertyGroup>
|
171
|
+
<second>$(first)</second>
|
172
|
+
<propertyName>property $(second)</propertyName>
|
173
|
+
<first>value</first>
|
174
|
+
</PropertyGroup>
|
175
|
+
</Project>
|
176
|
+
XML
|
177
|
+
|
178
|
+
properties = PropertyGroups.from_xml(text)
|
179
|
+
assert_equal("property value", properties.propertyName)
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_properties_can_be_loaded
|
183
|
+
text = <<XML
|
184
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
185
|
+
<PropertyGroup>
|
186
|
+
<weListenTasksPath Condition="'$(weListenTasksPath)' == ''">.</weListenTasksPath>
|
187
|
+
<weListenDependenciesTasksLib>$(weListenTasksPath)\\weListen.Dependencies.Tasks.dll</weListenDependenciesTasksLib>
|
188
|
+
</PropertyGroup>
|
189
|
+
</Project>
|
190
|
+
XML
|
191
|
+
|
192
|
+
PropertyGroups.from_xml(text)
|
193
|
+
end
|
194
|
+
|
195
|
+
"regression"
|
196
|
+
def test_properties_from_sdc
|
197
|
+
text = <<XML
|
198
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
199
|
+
<PropertyGroup>
|
200
|
+
<BuildPath Condition="'$(BuildPath)'==''">$(MSBuildProjectDirectory)\\</BuildPath>
|
201
|
+
<TasksPath Condition="Exists('$(BuildPath)\\bin\\Microsoft.Sdc.Tasks.dll')">$(BuildPath)\\bin\\</TasksPath>
|
202
|
+
</PropertyGroup>
|
203
|
+
</Project>
|
204
|
+
XML
|
205
|
+
|
206
|
+
properties = PropertyGroups.from_xml(text)
|
207
|
+
assert_equal("\\", properties.BuildPath)
|
208
|
+
assert_equal("\\\\bin\\", properties.TasksPath)
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'mocha'
|
4
|
+
require 'task_library'
|
5
|
+
require 'helper'
|
6
|
+
|
7
|
+
module TestNamespace
|
8
|
+
class TestTask
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class TaskLibraryNamespaces < Test::Unit::TestCase
|
13
|
+
class MockClass
|
14
|
+
class ClrType
|
15
|
+
attr_reader :name, :namespace
|
16
|
+
def initialize(name, namespace)
|
17
|
+
@name = name
|
18
|
+
@namespace = namespace
|
19
|
+
end
|
20
|
+
end
|
21
|
+
def initialize(name, namespace)
|
22
|
+
@name = name
|
23
|
+
@namespace = namespace
|
24
|
+
end
|
25
|
+
def to_clr_type
|
26
|
+
ClrType.new @name, @namespace
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_task_creates_method
|
31
|
+
tasks = [MockClass.new("test","")]
|
32
|
+
library = TaskLibrary.new(create_mock_engine, tasks)
|
33
|
+
assert_respond_to library, :test
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_different_libraries_should_have_different_tasks
|
37
|
+
tasks = [MockClass.new("first","")]
|
38
|
+
TaskLibrary.new(create_mock_engine, tasks)
|
39
|
+
|
40
|
+
tasks = [MockClass.new("second","")]
|
41
|
+
second_library = TaskLibrary.new(create_mock_engine, tasks)
|
42
|
+
assert_does_not_respond_to second_library, :first
|
43
|
+
assert_respond_to second_library, :second
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def test_task_with_namespace_is_accessible_via_namespaces
|
48
|
+
tasks = [MockClass.new("task","name.space")]
|
49
|
+
|
50
|
+
library = TaskLibrary.new(create_mock_engine, tasks)
|
51
|
+
assert_respond_to library.name.space, :task
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def test_library_has_namespaces_for_task
|
56
|
+
tasks = [MockClass.new("task","name.space")]
|
57
|
+
|
58
|
+
library = TaskLibrary.new(create_mock_engine, tasks)
|
59
|
+
assert_respond_to library.name, :space
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_library_has_two_namespaces
|
63
|
+
tasks = [MockClass.new("task","name.space.first"),
|
64
|
+
MockClass.new("other_task","name.space.second")]
|
65
|
+
|
66
|
+
library = TaskLibrary.new(create_mock_engine, tasks)
|
67
|
+
assert_respond_to library.name.space, :first
|
68
|
+
assert_respond_to library.name.space, :second
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_library_has_single_namespace_for_task
|
72
|
+
tasks = [MockClass.new("task","namespace")]
|
73
|
+
|
74
|
+
library = TaskLibrary.new(create_mock_engine, tasks)
|
75
|
+
assert_respond_to library, :namespace
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def create_mock_engine
|
80
|
+
mock()
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def assert_does_not_respond_to(object, method, message="")
|
85
|
+
full_message = build_message(nil, "<?>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to\\?(:to_str).", method)
|
86
|
+
|
87
|
+
assert_block(full_message) do
|
88
|
+
method.kind_of?(Symbol) || method.respond_to?(:to_str)
|
89
|
+
end
|
90
|
+
full_message = build_message(message, "<?>\nof type <?>\n expected to not respond_to\\\\?<?>.\n", object, object.class, method)
|
91
|
+
assert_block(full_message) { not object.respond_to?(method) }
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
data/test/tests_tasks.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'build_engine'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'mocha'
|
6
|
+
require 'pathname'
|
7
|
+
require 'stringio'
|
8
|
+
require 'helper'
|
9
|
+
|
10
|
+
module MSTaskTestUtil
|
11
|
+
def mstask_for_engine(build_engine)
|
12
|
+
TaskLibrary.from_modules(build_engine, Microsoft::Build::Tasks)
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_ruby_build_engine()
|
16
|
+
@output = StringIO.new
|
17
|
+
@output_logger = Logger.new(@output)
|
18
|
+
return RubyBuildEngine.new(@output_logger)
|
19
|
+
end
|
20
|
+
def mstask_library()
|
21
|
+
mstask_for_engine(default_ruby_build_engine())
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Message < Test::Unit::TestCase
|
26
|
+
include MSTaskTestUtil
|
27
|
+
|
28
|
+
def test_send_event_to_build_engine
|
29
|
+
build_engine = default_ruby_build_engine()
|
30
|
+
build_engine.expects(:log_message_event)
|
31
|
+
|
32
|
+
msbuild = mstask_for_engine(build_engine)
|
33
|
+
msbuild.Message :text => "Text"
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_message_appears_on_output
|
37
|
+
msbuild = mstask_for_engine(default_ruby_build_engine())
|
38
|
+
desired_text = "This is the text we'll be looking for"
|
39
|
+
msbuild.Message :text => desired_text
|
40
|
+
assert_not_nil(Regexp.new(desired_text).match(@output.string),
|
41
|
+
"Text not found in output")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class CommonMsbuildTasksAreLoaded < Test::Unit::TestCase
|
46
|
+
include MSTaskTestUtil
|
47
|
+
|
48
|
+
def test_delete
|
49
|
+
library = mstask_library()
|
50
|
+
assert_respond_to library , :Delete
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_message
|
54
|
+
library = mstask_library()
|
55
|
+
assert_respond_to library , :Message
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
class Delete < Test::Unit::TestCase
|
61
|
+
include MSTaskTestUtil
|
62
|
+
|
63
|
+
def test_delete_task_deletes_file
|
64
|
+
build_engine = default_ruby_build_engine()
|
65
|
+
msbuild = mstask_for_engine(build_engine)
|
66
|
+
|
67
|
+
filename = random_filepath()
|
68
|
+
FileUtils.touch filename
|
69
|
+
msbuild.Delete :files => filename
|
70
|
+
|
71
|
+
assert !File.exists?(filename)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_delete_task_deletes_two_files
|
75
|
+
build_engine = default_ruby_build_engine()
|
76
|
+
msbuild = mstask_for_engine(build_engine)
|
77
|
+
|
78
|
+
filenames = [random_filepath(), random_filepath()]
|
79
|
+
filenames.each { |filename| FileUtils.touch filename }
|
80
|
+
msbuild.Delete :files => filenames
|
81
|
+
|
82
|
+
filenames.each { |filename| !File.exists?(filename) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def setup
|
86
|
+
@@directory = "temp"
|
87
|
+
@@r = System::Random.new
|
88
|
+
clean_and_remove_directory()
|
89
|
+
Dir.mkdir(@@directory)
|
90
|
+
end
|
91
|
+
|
92
|
+
def teardown
|
93
|
+
clean_and_remove_directory()
|
94
|
+
end
|
95
|
+
|
96
|
+
def clean_and_remove_directory()
|
97
|
+
if File.exists?(@@directory) and File.directory?(@@directory)
|
98
|
+
FileUtils.remove_dir(@@directory)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def random_filepath
|
104
|
+
number_of_random_chars = 8
|
105
|
+
s = @@directory+"/"
|
106
|
+
number_of_random_chars.times { s << (65 + @@r.Next(26)) }
|
107
|
+
s
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class TasksFromTargetFile < Test::Unit::TestCase
|
112
|
+
include MSTaskTestUtil
|
113
|
+
|
114
|
+
|
115
|
+
def test_tasks_from_3_5_targets
|
116
|
+
directory = System::Environment.expand_environment_variables('%WINDIR%\Microsoft.NET\Framework\v3.5')
|
117
|
+
file_name = "Microsoft.Common.Tasks"
|
118
|
+
full_path = System::IO::Path.combine(directory, file_name)
|
119
|
+
build_engine = default_ruby_build_engine()
|
120
|
+
|
121
|
+
task_library = TaskLibrary.from_tasks_file(build_engine, full_path)
|
122
|
+
assert(task_library.respond_to?(:AssignProjectConfiguration),
|
123
|
+
"Task library should have 'AssignAssignProjectConfiguration' task")
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ironbuildrake
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ironruby
|
6
|
+
authors:
|
7
|
+
- Bruno Lopes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: !timestamp "2009-12-26 00:00:00 "
|
12
|
+
default_executable:
|
13
|
+
dependencies: []
|
14
|
+
description: ""
|
15
|
+
email: brunomlopes@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README
|
20
|
+
files:
|
21
|
+
- README
|
22
|
+
- Rakefile
|
23
|
+
- VERSION
|
24
|
+
- ironbuildrake.gemspec
|
25
|
+
- lib/Microsoft.Build.Tasks.rb
|
26
|
+
- lib/assembly_loader.rb
|
27
|
+
- lib/build_engine.rb
|
28
|
+
- lib/namespace_node.rb
|
29
|
+
- lib/task_item.rb
|
30
|
+
- lib/task_library.rb
|
31
|
+
- lib/tasks_file.rb
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/brunomlopes/ironbuildrake
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --charset=UTF-8
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: !str 0
|
45
|
+
version:
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: !str 0
|
51
|
+
version:
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.3.5
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Adds support for using msbuild tasks in ironruby with rake
|
58
|
+
test_files:
|
59
|
+
- test/helper.rb
|
60
|
+
- test/tests_namespace_node.rb
|
61
|
+
- test/tests_other_libraries.rb
|
62
|
+
- test/tests_targets_file.rb
|
63
|
+
- test/tests_tasks.rb
|
64
|
+
- test/tests_task_library.rb
|