bozo-scripts 0.1.5 → 0.1.6
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 +8 -8
- data/LICENSE +19 -0
- data/VERSION +1 -0
- data/lib/bozo/compilers/msbuild.rb +279 -0
- data/lib/bozo/configuration.rb +155 -0
- data/lib/bozo/dependency_resolvers/bundler.rb +54 -0
- data/lib/bozo/dependency_resolvers/nuget.rb +86 -0
- data/lib/bozo/erubis_templating_coordinator.rb +128 -0
- data/lib/bozo/hooks/fxcop.rb +152 -0
- data/lib/bozo/hooks/git_commit_hashes.rb +12 -0
- data/lib/bozo/hooks/git_tag_release.rb +23 -0
- data/lib/bozo/hooks/teamcity.rb +92 -0
- data/lib/bozo/hooks/timing.rb +41 -0
- data/lib/bozo/packagers/nuget.rb +226 -0
- data/lib/bozo/packagers/rubygems.rb +24 -0
- data/lib/bozo/preparers/common_assembly_info.rb +34 -0
- data/lib/bozo/preparers/file_templating.rb +152 -0
- data/lib/bozo/publishers/file_copy.rb +83 -0
- data/lib/bozo/publishers/rubygems.rb +18 -0
- data/lib/bozo/test_runners/dotcover.rb +158 -0
- data/lib/bozo/test_runners/nunit.rb +131 -0
- data/lib/bozo/test_runners/runit.rb +35 -0
- data/lib/bozo/version.rb +5 -0
- data/lib/bozo_scripts.rb +26 -0
- metadata +25 -2
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
|
3
|
+
module Bozo
|
4
|
+
|
5
|
+
# Class for creating files based upon configuration files and ERB-style
|
6
|
+
# templates.
|
7
|
+
#
|
8
|
+
# == Overview
|
9
|
+
#
|
10
|
+
# This class is primarily intended for generating config files with shared
|
11
|
+
# values but it is capable of generating whatever files you want.
|
12
|
+
#
|
13
|
+
# == Configuration files
|
14
|
+
#
|
15
|
+
# Configuration files specify a hash of hashes in a more readable format.
|
16
|
+
# For example:
|
17
|
+
#
|
18
|
+
# group :example do
|
19
|
+
# set :one, 'foo'
|
20
|
+
# set :two, 'bar'
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Internally creates a hash like:
|
24
|
+
#
|
25
|
+
# {:example => {:one => 'foo', :two => 'bar'}}
|
26
|
+
#
|
27
|
+
# A configuration file can overwrite the values specified by a preceding one
|
28
|
+
# without error. Groups can be opened and closed as desired and nesting
|
29
|
+
# groups is possible.
|
30
|
+
#
|
31
|
+
# == Template files
|
32
|
+
#
|
33
|
+
# To use a value within an ERB template you specify the hash hierarchy as if
|
34
|
+
# they were method names rather than having to use the full hash syntax.
|
35
|
+
#
|
36
|
+
# Therefore, this is valid:
|
37
|
+
#
|
38
|
+
# Foo is <%= example.one %>
|
39
|
+
#
|
40
|
+
# Whilst this is *not* valid:
|
41
|
+
#
|
42
|
+
# Foo is <%= self[:example][:one] %>
|
43
|
+
#
|
44
|
+
# If a template uses a value that is not specified within the configuration
|
45
|
+
# then the hook will raise an error and halt the build.
|
46
|
+
class ErubisTemplatingCoordinator
|
47
|
+
|
48
|
+
# Create a new instance.
|
49
|
+
#
|
50
|
+
# @param [Configuration] configuration
|
51
|
+
# The configuration to use with templates. If not specified a new
|
52
|
+
# object is created.
|
53
|
+
def initialize(configuration = Bozo::Configuration.new)
|
54
|
+
@templates = []
|
55
|
+
@configuration = configuration
|
56
|
+
end
|
57
|
+
|
58
|
+
# Adds a required configuration file to the underlying configuration
|
59
|
+
# object.
|
60
|
+
#
|
61
|
+
# @param [String] path
|
62
|
+
# The path of the configuration file to load.
|
63
|
+
def required_config_file(path)
|
64
|
+
raise RuntimeError.new "Required config file #{path} could not be found" unless File.exist? path
|
65
|
+
config_file path
|
66
|
+
end
|
67
|
+
|
68
|
+
# Adds a configuration file to the underlying configuration object if a
|
69
|
+
# file exists at the given path.
|
70
|
+
#
|
71
|
+
# @param [String] path
|
72
|
+
# The path of the configuration file to load.
|
73
|
+
def config_file(path)
|
74
|
+
@configuration.load path if File.exist? path
|
75
|
+
end
|
76
|
+
|
77
|
+
# Adds a template file to use when generating files.
|
78
|
+
#
|
79
|
+
# @param [String] path
|
80
|
+
# The path of the template file.
|
81
|
+
def template_file(path)
|
82
|
+
@templates << path
|
83
|
+
end
|
84
|
+
|
85
|
+
# Adds a selection of template files to use when generating files.
|
86
|
+
#
|
87
|
+
# @param [String] glob
|
88
|
+
# A glob from that matches template files.
|
89
|
+
def template_files(glob)
|
90
|
+
@templates = @templates + Dir[glob]
|
91
|
+
end
|
92
|
+
|
93
|
+
# Generate all the files matching the underlying configuration.
|
94
|
+
#
|
95
|
+
# @param [Proc] block
|
96
|
+
# A block that will be called with the template path and target file
|
97
|
+
# path when provided.
|
98
|
+
def generate_files(&block)
|
99
|
+
@templates.each {|template| generate_file template, block}
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# Generate the file relating to the template file using the given
|
105
|
+
# configuration.
|
106
|
+
#
|
107
|
+
# @param [String] template_path
|
108
|
+
# The path of the template file that should be filled using the
|
109
|
+
# configuration.
|
110
|
+
# @param [Proc] block
|
111
|
+
# A block that will be called with the template path and target file
|
112
|
+
# path when provided.
|
113
|
+
def generate_file(template_path, block)
|
114
|
+
target_path = template_path.sub /\.[^\.]+$/, ''
|
115
|
+
|
116
|
+
block.call(template_path, target_path) unless block.nil?
|
117
|
+
|
118
|
+
template_content = IO.read template_path
|
119
|
+
template = Erubis::Eruby.new template_content
|
120
|
+
|
121
|
+
content = @configuration.apply {|binding| template.result(binding)}
|
122
|
+
|
123
|
+
File.open(target_path, 'w+') {|f| f.write(content)}
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module Bozo::Hooks
|
2
|
+
|
3
|
+
# Specifies a hook for running FxCop.
|
4
|
+
#
|
5
|
+
# The default configuration runs against the compiled assemblies produced via
|
6
|
+
# msbuild.
|
7
|
+
#
|
8
|
+
# Alternatively a specific .fxcop project file can be specified in the
|
9
|
+
# configuration.
|
10
|
+
class FxCop
|
11
|
+
|
12
|
+
def self.default_path
|
13
|
+
if ENV['ProgramFiles(x86)'].nil?
|
14
|
+
program_files_path = ENV['ProgramFiles']
|
15
|
+
else
|
16
|
+
program_files_path = ENV['ProgramFiles(x86)']
|
17
|
+
end
|
18
|
+
|
19
|
+
File.join(program_files_path, 'Microsoft Fxcop 10.0', 'fxcopcmd.exe') unless program_files_path.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@@defaults = {
|
24
|
+
:types => [],
|
25
|
+
:framework_versions => [:net35, :net40],
|
26
|
+
:project => nil,
|
27
|
+
:path => FxCop.default_path
|
28
|
+
}
|
29
|
+
|
30
|
+
@config = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Adds a type to analyze
|
34
|
+
def type(type)
|
35
|
+
@config[:types] ||= []
|
36
|
+
@config[:types] << type
|
37
|
+
end
|
38
|
+
|
39
|
+
# Specifies an fxcop project file
|
40
|
+
def project(project)
|
41
|
+
@config[:project] = project
|
42
|
+
end
|
43
|
+
|
44
|
+
# Specifies the fxcop path
|
45
|
+
def path(path = nil)
|
46
|
+
@config[:path] = path unless path.nil?
|
47
|
+
|
48
|
+
@config[:path]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Runs the post_compile hook
|
52
|
+
def post_compile
|
53
|
+
config = config_with_defaults
|
54
|
+
|
55
|
+
raise no_executable_path_specified if path.nil?
|
56
|
+
raise no_executable_exists unless File.exists?(path)
|
57
|
+
|
58
|
+
if config[:project].nil?
|
59
|
+
execute_projects config
|
60
|
+
else
|
61
|
+
execute_fxcop_project config
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def config_with_defaults
|
68
|
+
@@defaults.merge @config
|
69
|
+
end
|
70
|
+
|
71
|
+
# The path to output the fxcop results to
|
72
|
+
def output_path
|
73
|
+
out_path = File.expand_path File.join('temp', 'fxcop')
|
74
|
+
FileUtils.mkdir_p out_path
|
75
|
+
out_path
|
76
|
+
end
|
77
|
+
|
78
|
+
# Executes fxcop against the msbuild built assemblies
|
79
|
+
#
|
80
|
+
# @param [Hash] config
|
81
|
+
# The fxcop configuration
|
82
|
+
def execute_projects(config)
|
83
|
+
log_debug "Executing projects with '#{path}'" if config[:framework_versions].any?
|
84
|
+
|
85
|
+
config[:framework_versions].each do |framework_version|
|
86
|
+
args = []
|
87
|
+
args << '"' + path + '"'
|
88
|
+
args << "/out:#{output_path}\\#{Time.now.to_i}-#{framework_version}-FxCop-report.xml"
|
89
|
+
args << "/types:" + config[:types].join(',') unless config[:types].empty?
|
90
|
+
|
91
|
+
project_dirs.each do |project|
|
92
|
+
projects = project_files(project, framework_version)
|
93
|
+
|
94
|
+
projects.each do |project_file|
|
95
|
+
project_path = File.expand_path(project_file).gsub(/\//, '\\')
|
96
|
+
args << "/file:\"#{project_path}\""
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
execute_command :fx_cop, args
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Executes a .fxcop file
|
105
|
+
#
|
106
|
+
# @param [Hash] config
|
107
|
+
# The fxcop configuration
|
108
|
+
def execute_fxcop_project(config)
|
109
|
+
log_debug "Executing fxcop project '#{config[:project]}' with '#{path}'"
|
110
|
+
|
111
|
+
args = []
|
112
|
+
args << '"' + path + '"'
|
113
|
+
args << "/out:\"#{output_path}\\#{File.basename(config[:project], '.*')}-FxCop-report.xml\""
|
114
|
+
args << "/project:\"#{config[:project]}\""
|
115
|
+
args << "/types:" + config[:types].join(',') unless config[:types].empty?
|
116
|
+
|
117
|
+
execute_command :fx_cop, args
|
118
|
+
end
|
119
|
+
|
120
|
+
# Create a new error specifying that the executable path
|
121
|
+
# has not been specified.
|
122
|
+
def no_executable_path_specified
|
123
|
+
ConfigurationError.new "No path specified for fxcop"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Create a new error specifying that the fxcop executable
|
127
|
+
# does not exist at the path.
|
128
|
+
def no_executable_exists
|
129
|
+
ConfigurationError.new "FxCop executable does not exist at #{path}"
|
130
|
+
end
|
131
|
+
|
132
|
+
# List of compiled assemblies and executables
|
133
|
+
|
134
|
+
# @param [String] project_path
|
135
|
+
# The path of the project
|
136
|
+
# @param [Symbol] framework_version
|
137
|
+
# The framework_version to find assemblies for
|
138
|
+
def project_files(project_path, framework_version)
|
139
|
+
project_name = File.basename(project_path)
|
140
|
+
file_matcher = File.expand_path File.join(project_path, framework_version.to_s, "#{project_name}.{dll,exe}")
|
141
|
+
Dir[file_matcher]
|
142
|
+
end
|
143
|
+
|
144
|
+
# List of all the msbuild built projects
|
145
|
+
def project_dirs
|
146
|
+
project_file_matcher = File.expand_path File.join('temp', 'msbuild', '*')
|
147
|
+
Dir[project_file_matcher]
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Bozo::Hooks
|
2
|
+
|
3
|
+
# Hook to tag a git repository when a release is published from a build
|
4
|
+
# server.
|
5
|
+
class GitTagRelease
|
6
|
+
|
7
|
+
def post_publish
|
8
|
+
return unless build_server?
|
9
|
+
log_info "Tagging repository for release #{version}"
|
10
|
+
|
11
|
+
tag_name = "rel-#{version}"
|
12
|
+
|
13
|
+
if `git tag`.split("\n").include? tag_name
|
14
|
+
raise Bozo::ConfigurationError.new "The tag #{tag_name} already exists"
|
15
|
+
end
|
16
|
+
|
17
|
+
execute_command :git, ['git', 'tag', tag_name]
|
18
|
+
execute_command :git, ['git', 'push', '--tags']
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Bozo::Hooks
|
2
|
+
|
3
|
+
class Teamcity
|
4
|
+
|
5
|
+
include Bozo::ClassNameHelpers
|
6
|
+
|
7
|
+
def pre_compile
|
8
|
+
return unless Teamcity.hosted_in_teamcity?
|
9
|
+
log_pre_step :compile
|
10
|
+
|
11
|
+
puts "##teamcity[buildNumber '#{version}']"
|
12
|
+
# currently a general compiler which wraps everything. Once a compiler hook is added can distinguish
|
13
|
+
# each specific compiler
|
14
|
+
puts "##teamcity[compilationStarted compiler='Bozo']"
|
15
|
+
end
|
16
|
+
|
17
|
+
def post_compile
|
18
|
+
return unless Teamcity.hosted_in_teamcity?
|
19
|
+
puts "##teamcity[compilationFinished compiler='Bozo']"
|
20
|
+
log_post_step :compile
|
21
|
+
end
|
22
|
+
|
23
|
+
def post_test
|
24
|
+
return unless Teamcity.hosted_in_teamcity?
|
25
|
+
|
26
|
+
report
|
27
|
+
report_dotnetcoverage
|
28
|
+
|
29
|
+
log_post_step :test
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_missing(method, *args)
|
33
|
+
if method.to_s =~ /^(pre|post)_(.+)/
|
34
|
+
send "log_#{$1}_step".to_sym, $2
|
35
|
+
else
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def respond_to?(method)
|
41
|
+
method.to_s =~ /^(pre|post)_(.+)/ or super
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns whether teamcity is hosting bozo
|
45
|
+
def self.hosted_in_teamcity?
|
46
|
+
not ENV['TEAMCITY_VERSION'].nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# Notifies teamcity of general reports such as test runner results
|
52
|
+
def report
|
53
|
+
report_types = [:nunit, :fxcop]
|
54
|
+
report_types.each do |type|
|
55
|
+
reports = report_files(File.join(Dir.pwd, "/temp"), type)
|
56
|
+
|
57
|
+
reports.each do |report|
|
58
|
+
puts "##teamcity[importData type='#{type}' path='#{report}']"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Notifies teamcity of dotNetCoverage results
|
64
|
+
def report_dotnetcoverage
|
65
|
+
tool_types = [:dot_cover]
|
66
|
+
|
67
|
+
tool_types.each do |type|
|
68
|
+
reports = report_files(File.join(Dir.pwd, "/temp"), type)
|
69
|
+
|
70
|
+
reports.each do |report|
|
71
|
+
tool_name = to_class_name(type).downcase
|
72
|
+
puts "##teamcity[importData type='dotNetCoverage' tool='#{tool_name}' path='#{report}']"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def log_pre_step(step)
|
78
|
+
puts "##teamcity[progressStart 'Pre #{step}']" if Teamcity.hosted_in_teamcity?
|
79
|
+
end
|
80
|
+
|
81
|
+
def log_post_step(step)
|
82
|
+
puts "##teamcity[progressEnd 'Post #{step}']" if Teamcity.hosted_in_teamcity?
|
83
|
+
end
|
84
|
+
|
85
|
+
def report_files(path, type)
|
86
|
+
files = File.expand_path(File.join(path, "/**/*-#{to_class_name(type)}-report.xml"))
|
87
|
+
Dir[files]
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Bozo::Hooks
|
2
|
+
|
3
|
+
class Timing
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@timings = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def print_timings
|
10
|
+
puts ''
|
11
|
+
@timings.each do |stage, times|
|
12
|
+
puts format_timing(stage, times).bright.color(stage == :build ? :cyan : :black)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def format_timing(stage, args)
|
17
|
+
time_taken = (args[:post] - args[:pre]).round(1)
|
18
|
+
"#{stage.to_s.capitalize.ljust(14)} #{time_taken.to_s.rjust(5)}s"
|
19
|
+
end
|
20
|
+
|
21
|
+
def record(stage, point)
|
22
|
+
@timings[stage] ||= {}
|
23
|
+
@timings[stage][point] = Time.now
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(method, *args)
|
27
|
+
if method.to_s =~ /^(pre|post)_(.+)/
|
28
|
+
record $2.to_sym, $1.to_sym
|
29
|
+
print_timings if $1 == 'post' and $2 == 'build'
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def respond_to?(method)
|
36
|
+
method.to_s =~ /^(pre|post)_(.+)/ or super
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Bozo::Packagers
|
4
|
+
|
5
|
+
class Nuget
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@libraries = []
|
9
|
+
@executables = []
|
10
|
+
@websites = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def destination(destination)
|
14
|
+
@destination = destination
|
15
|
+
end
|
16
|
+
|
17
|
+
def library(project)
|
18
|
+
@libraries << LibraryPackage.new(project, self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def executable(project)
|
22
|
+
@executables << ExecutablePackage.new(project)
|
23
|
+
end
|
24
|
+
|
25
|
+
def website(project)
|
26
|
+
@websites << WebsitePackage.new(project)
|
27
|
+
end
|
28
|
+
|
29
|
+
def required_tools
|
30
|
+
:nuget
|
31
|
+
end
|
32
|
+
|
33
|
+
def project_url(url)
|
34
|
+
@project_url = url
|
35
|
+
end
|
36
|
+
|
37
|
+
def license_url(url)
|
38
|
+
@license_url = url
|
39
|
+
end
|
40
|
+
|
41
|
+
def author(author)
|
42
|
+
@author = author
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
"Publish projects with nuget #{@libraries | @executables | @websites} to #{@destination}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def execute
|
50
|
+
@libraries.each {|project| package project}
|
51
|
+
@executables.each {|project| package project}
|
52
|
+
@websites.each {|project| package project}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the version that the package should be given.
|
56
|
+
def package_version
|
57
|
+
# If running on a build server then it is a real release, otherwise it is
|
58
|
+
# a preview release and the version should reflect that.
|
59
|
+
if build_server?
|
60
|
+
version
|
61
|
+
else
|
62
|
+
"#{version}-pre#{env['GIT_HASH']}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def package(project)
|
69
|
+
spec_path = generate_specification(project)
|
70
|
+
create_package(project.name, spec_path, true)
|
71
|
+
end
|
72
|
+
|
73
|
+
def generate_specification(project)
|
74
|
+
log_debug "Generating specification for #{project.name}"
|
75
|
+
builder = Nokogiri::XML::Builder.new do |doc|
|
76
|
+
doc.package(:xmlns => "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd") do
|
77
|
+
doc.metadata do
|
78
|
+
doc.id project.name
|
79
|
+
doc.version_ package_version
|
80
|
+
doc.authors @author
|
81
|
+
doc.description project.name
|
82
|
+
doc.projectUrl @project_url
|
83
|
+
doc.licenseUrl @license_url
|
84
|
+
doc.dependencies do
|
85
|
+
project.dependencies.each do |dep|
|
86
|
+
doc.dependency(dep)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
doc.files do
|
91
|
+
project.files.each do |file|
|
92
|
+
doc.file(file)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
spec_path = File.expand_path(File.join('temp', 'nuget', "#{project.name}.nuspec"))
|
98
|
+
FileUtils.mkdir_p File.dirname(spec_path)
|
99
|
+
File.open(spec_path, 'w+') {|f| f.write(builder.to_xml)}
|
100
|
+
spec_path
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_package(project, spec_path, omit_analysis = false)
|
104
|
+
args = []
|
105
|
+
|
106
|
+
dist_dir = File.expand_path(File.join('dist', 'nuget'))
|
107
|
+
|
108
|
+
args << File.expand_path(File.join('build', 'tools', 'nuget', 'NuGet.exe'))
|
109
|
+
args << 'pack'
|
110
|
+
args << "\"#{spec_path}\""
|
111
|
+
args << '-OutputDirectory'
|
112
|
+
args << "\"#{dist_dir}\""
|
113
|
+
args << '-NoPackageAnalysis' if omit_analysis
|
114
|
+
|
115
|
+
# Ensure the directory is there because Nuget won't make it
|
116
|
+
FileUtils.mkdir_p dist_dir
|
117
|
+
|
118
|
+
log_debug "Creating nuget package for #{project}"
|
119
|
+
|
120
|
+
execute_command :nuget, args
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
class ExecutablePackage
|
128
|
+
|
129
|
+
def initialize(project)
|
130
|
+
@name = project
|
131
|
+
end
|
132
|
+
|
133
|
+
def name
|
134
|
+
@name
|
135
|
+
end
|
136
|
+
|
137
|
+
def dependencies
|
138
|
+
[]
|
139
|
+
end
|
140
|
+
|
141
|
+
def files
|
142
|
+
[{:src => File.expand_path(File.join('temp', 'msbuild', @name, '**', '*.*')).gsub(/\//, '\\'), :target => 'exe'}]
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
class LibraryPackage
|
148
|
+
|
149
|
+
def initialize(project, nuget)
|
150
|
+
@name = project
|
151
|
+
@nuget = nuget
|
152
|
+
end
|
153
|
+
|
154
|
+
def name
|
155
|
+
@name
|
156
|
+
end
|
157
|
+
|
158
|
+
def dependencies
|
159
|
+
project_reference_dependencies + nuget_dependencies
|
160
|
+
end
|
161
|
+
|
162
|
+
def files
|
163
|
+
%w{dll pdb xml}.map do |extension|
|
164
|
+
{:src => File.expand_path(File.join('temp', 'msbuild', @name, '**', "#{@name}.#{extension}")).gsub(/\//, '\\'), :target => 'lib'}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
def project_reference_dependencies
|
171
|
+
doc = Nokogiri::XML(File.open(project_file))
|
172
|
+
|
173
|
+
doc.xpath('//proj:Project/proj:ItemGroup/proj:ProjectReference/proj:Name', {"proj" => "http://schemas.microsoft.com/developer/msbuild/2003"}).map do |node|
|
174
|
+
{:id => node.text, :version => "[#{@nuget.package_version}]"}
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# get dependencies from packages.config
|
179
|
+
def nuget_dependencies
|
180
|
+
package_file = packages_file
|
181
|
+
return [] unless File.exist? package_file
|
182
|
+
|
183
|
+
doc = Nokogiri::XML(File.open(package_file))
|
184
|
+
|
185
|
+
doc.xpath('//packages/package').map do |node|
|
186
|
+
{:id => node[:id], :version => "[#{node[:version]}]"}
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def packages_file
|
191
|
+
find_file_in_project 'packages.config'
|
192
|
+
end
|
193
|
+
|
194
|
+
def project_file
|
195
|
+
find_file_in_project "#{@name}.csproj"
|
196
|
+
end
|
197
|
+
|
198
|
+
def find_file_in_project(file_name)
|
199
|
+
file = File.expand_path(File.join('src', 'csharp', @name, file_name))
|
200
|
+
file = File.expand_path(File.join('test', 'csharp', @name, file_name)) unless File.exist? file
|
201
|
+
file
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
class WebsitePackage
|
207
|
+
|
208
|
+
def initialize(project)
|
209
|
+
@name = project
|
210
|
+
end
|
211
|
+
|
212
|
+
def name
|
213
|
+
@name
|
214
|
+
end
|
215
|
+
|
216
|
+
def dependencies
|
217
|
+
[]
|
218
|
+
end
|
219
|
+
|
220
|
+
def files
|
221
|
+
[{:src => File.expand_path(File.join('temp', 'msbuild', @name, '**', '*.*')).gsub(/\//, '\\'), :target => 'website'}]
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Bozo::Packagers
|
2
|
+
|
3
|
+
# Specifies gem packager.
|
4
|
+
#
|
5
|
+
# Builds any '*.gemspec' file in the root directory
|
6
|
+
class Rubygems
|
7
|
+
|
8
|
+
def execute
|
9
|
+
dist_dir = File.expand_path(File.join('dist', 'gem'))
|
10
|
+
FileUtils.mkdir_p dist_dir
|
11
|
+
|
12
|
+
Dir['*.gemspec'].each { |spec| build_gem spec }
|
13
|
+
Dir['*.gem'].each { |file| FileUtils.mv file, File.join(dist_dir, file) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def build_gem(spec)
|
19
|
+
execute_command :rubygems, ['gem', 'build', spec]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|