alpacabuildtool 1.0.0
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 +48 -0
- data/.rubocop.yml +12 -0
- data/.semver +6 -0
- data/.travis.yml +10 -0
- data/CHANGELOG +18 -0
- data/Gemfile +7 -0
- data/LICENSE +22 -0
- data/README.md +235 -0
- data/README.rdoc +39 -0
- data/Rakefile +74 -0
- data/alpacabuildtool.gemspec +34 -0
- data/alpacabuildtool.rdoc +5 -0
- data/alpacabuildtool.todo +9 -0
- data/bin/alpaca +142 -0
- data/features/alpaca.feature +8 -0
- data/features/step_definitions/alpaca_steps.rb +13 -0
- data/features/step_definitions/visual_studio_solutions_steps.rb +47 -0
- data/features/support/env.rb +10 -0
- data/features/visual_studio_solutions.feature +43 -0
- data/lib/alpacabuildtool.rb +4 -0
- data/lib/alpacabuildtool/application.rb +195 -0
- data/lib/alpacabuildtool/configuration.rb +209 -0
- data/lib/alpacabuildtool/data/.alpaca.conf +148 -0
- data/lib/alpacabuildtool/data/doom.flf +826 -0
- data/lib/alpacabuildtool/data/logo.jpg +0 -0
- data/lib/alpacabuildtool/entities/nuspec.rb +107 -0
- data/lib/alpacabuildtool/entities/project.rb +54 -0
- data/lib/alpacabuildtool/entities/solution.rb +104 -0
- data/lib/alpacabuildtool/entities/xml.rb +41 -0
- data/lib/alpacabuildtool/entities/xml_node.rb +75 -0
- data/lib/alpacabuildtool/log/font.rb +92 -0
- data/lib/alpacabuildtool/log/log.rb +15 -0
- data/lib/alpacabuildtool/log/rainbowify_formatter.rb +70 -0
- data/lib/alpacabuildtool/log/rainbowify_logger.rb +47 -0
- data/lib/alpacabuildtool/managers/build_manager.rb +32 -0
- data/lib/alpacabuildtool/managers/package_manager.rb +136 -0
- data/lib/alpacabuildtool/managers/report_manager.rb +33 -0
- data/lib/alpacabuildtool/managers/test_manager.rb +35 -0
- data/lib/alpacabuildtool/os.rb +29 -0
- data/lib/alpacabuildtool/package_types/project_package.rb +44 -0
- data/lib/alpacabuildtool/package_types/tool_package.rb +53 -0
- data/lib/alpacabuildtool/tools/git.rb +22 -0
- data/lib/alpacabuildtool/tools/msbuild.rb +29 -0
- data/lib/alpacabuildtool/tools/nuget.rb +49 -0
- data/lib/alpacabuildtool/tools/nunit.rb +28 -0
- data/lib/alpacabuildtool/tools/nunit_orange.rb +18 -0
- data/lib/alpacabuildtool/tools/open_cover.rb +29 -0
- data/lib/alpacabuildtool/tools/report_generator.rb +25 -0
- data/lib/alpacabuildtool/tools/tool.rb +84 -0
- data/lib/alpacabuildtool/tools/wrapper.rb +66 -0
- data/lib/alpacabuildtool/versioning/version.rb +163 -0
- data/lib/alpacabuildtool/versioning/versioning.rb +84 -0
- data/spec/lib/alpacabuildtool/configuration_spec.rb +201 -0
- data/spec/lib/alpacabuildtool/entities/xml_spec.rb +39 -0
- data/spec/lib/alpacabuildtool/versioning/version_spec.rb +86 -0
- data/spec/lib/alpacabuildtool/versioning/versioning_spec.rb +194 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/coverage.rb +26 -0
- data/test_data/sln1/.alpaca.conf +11 -0
- data/test_data/sln1/.semver +6 -0
- data/test_data/sln1/TestSolution.sln +22 -0
- data/test_data/sln1/TestSolution/App.config +6 -0
- data/test_data/sln1/TestSolution/Program.cs +16 -0
- data/test_data/sln1/TestSolution/Properties/AssemblyInfo.cs +36 -0
- data/test_data/sln1/TestSolution/TestSolution.csproj +59 -0
- data/test_data/sln2/.alpaca.conf +8 -0
- data/test_data/sln2/.semver +6 -0
- data/test_data/sln2/ProjectName/ProjectName.csproj +54 -0
- data/test_data/sln2/ProjectName/Properties/AssemblyInfo.cs +36 -0
- data/test_data/sln2/ProjectName/SomeFolderInProject/SomeClass.cs +16 -0
- data/test_data/sln2/ProjectName2/ProjectName2.csproj +58 -0
- data/test_data/sln2/ProjectName2/Properties/AssemblyInfo.cs +37 -0
- data/test_data/sln2/SolutionName.sln +34 -0
- data/test_data/sln2/Unit.Tests/Properties/AssemblyInfo.cs +36 -0
- data/test_data/sln2/Unit.Tests/SomeClassTests.cs +21 -0
- data/test_data/sln2/Unit.Tests/Unit.Tests.csproj +65 -0
- data/test_data/sln2/Unit.Tests/packages.config +4 -0
- data/test_data/sln3/TestSolution.nobuild.sln +22 -0
- data/test_data/sln3/TestSolution/App.config +6 -0
- data/test_data/sln3/TestSolution/Program.cs +16 -0
- data/test_data/sln3/TestSolution/Properties/AssemblyInfo.cs +36 -0
- data/test_data/sln3/TestSolution/TestSolution.nobuild.csproj +59 -0
- metadata +309 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module AlpacaBuildTool
|
|
4
|
+
##
|
|
5
|
+
# ProjectPackage provides configuration of normal nuget packages created
|
|
6
|
+
# from projects
|
|
7
|
+
class ToolPackage
|
|
8
|
+
##
|
|
9
|
+
# Defines workspace where files should be copied for further packaging
|
|
10
|
+
# and where *.nuspec, readme and changelog should be created
|
|
11
|
+
# For now it's ~/.workspace
|
|
12
|
+
WORKSPACE = File.join(File.expand_path('~'), '.workspace/')
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# Creates an instance
|
|
16
|
+
#
|
|
17
|
+
# +package_id+:: package id so workspace is not messed up
|
|
18
|
+
# +project+:: project to be used to create a package
|
|
19
|
+
# +debug+:: is debug configuration should be used to create a package
|
|
20
|
+
#
|
|
21
|
+
# *It clean workspace/package_id folder and copy files from project/bin*
|
|
22
|
+
def initialize(package_id, project, debug)
|
|
23
|
+
workspace = File.join(WORKSPACE, package_id)
|
|
24
|
+
FileUtils.rm_rf(workspace)
|
|
25
|
+
FileUtils.makedirs(workspace + '/tools')
|
|
26
|
+
tool_path = File.join(project.dir, 'bin', debug ? 'Debug' : 'Release')
|
|
27
|
+
FileUtils.copy_entry(tool_path, workspace + '/tools')
|
|
28
|
+
@nuspec_file = File.join(workspace, "#{package_id}.nuspec")
|
|
29
|
+
@readme_file = File.join(workspace, 'README.txt')
|
|
30
|
+
@changelog_file = File.join(workspace, 'CHANGES.txt')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Returns array of files: *.nuspec, CHANGELOG.txt, README.txt
|
|
35
|
+
def files
|
|
36
|
+
[@nuspec_file, @changelog_file, @readme_file]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def options
|
|
40
|
+
[@nuspec_file]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Returns false so Nuspec file creation process will not store readme and
|
|
45
|
+
# changelog files into <files/> entry
|
|
46
|
+
#
|
|
47
|
+
# This is required for tools packages as they are created from folder
|
|
48
|
+
# and they will miss tool files if <files/> entry will exist in *.nuspec
|
|
49
|
+
def add_files?
|
|
50
|
+
false
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module AlpacaBuildTool
|
|
2
|
+
##
|
|
3
|
+
# Git provides methods to help with git version control tool
|
|
4
|
+
module Git
|
|
5
|
+
##
|
|
6
|
+
# Returns string with changes in dir
|
|
7
|
+
#
|
|
8
|
+
# +dir+:: specific dir where to look for changes
|
|
9
|
+
# +commit_from+:: commit from which look for changes(nil by default to
|
|
10
|
+
# look for all changes)
|
|
11
|
+
def self.changes(dir, commit_from = nil)
|
|
12
|
+
return `git log -- #{dir}` unless commit_from
|
|
13
|
+
`git log #{commit_from}..HEAD -- #{dir}`
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Returns current revision id
|
|
18
|
+
def self.revision
|
|
19
|
+
`git rev-parse HEAD`
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'alpacabuildtool/tools/tool'
|
|
2
|
+
|
|
3
|
+
module AlpacaBuildTool
|
|
4
|
+
##
|
|
5
|
+
# MSBuild provides access to MSBuild.exe tool
|
|
6
|
+
class MSBuild < Tool
|
|
7
|
+
##
|
|
8
|
+
# Build *.sln file
|
|
9
|
+
#
|
|
10
|
+
# +file+:: solution file with absolute path
|
|
11
|
+
# +debug+:: set to build with debug configuration
|
|
12
|
+
def build(file, debug = false)
|
|
13
|
+
config = @configuration['options'].dup
|
|
14
|
+
config['Property'] ||= {}
|
|
15
|
+
config['Property']['Configuration'] = debug ? 'Debug' : 'Release'
|
|
16
|
+
call([config, file])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def format_option(name, value, switch)
|
|
22
|
+
case value
|
|
23
|
+
when Array then value = value.join(';')
|
|
24
|
+
when Hash then value = value.map { |k, v| "#{k}=#{v}" }.join(';')
|
|
25
|
+
end
|
|
26
|
+
super name, value, switch
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'alpacabuildtool/tools/tool'
|
|
3
|
+
|
|
4
|
+
module AlpacaBuildTool
|
|
5
|
+
# tool
|
|
6
|
+
class Nuget < Tool
|
|
7
|
+
def restore(solution_file)
|
|
8
|
+
run_command 'restore', solution_file
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def install(package,
|
|
12
|
+
outputdir = nil,
|
|
13
|
+
prerelease = false,
|
|
14
|
+
exclude_version = false,
|
|
15
|
+
source = nil)
|
|
16
|
+
extra_options = {}
|
|
17
|
+
extra_options['OutputDirectory'] = outputdir if outputdir
|
|
18
|
+
extra_options['Prerelease'] = prerelease if prerelease
|
|
19
|
+
extra_options['ExcludeVersion'] = exclude_version if exclude_version
|
|
20
|
+
extra_options['Source'] = source if source
|
|
21
|
+
run_command 'install', package, extra_options
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def pack(nuspec_or_project, configuration = nil)
|
|
25
|
+
extra_options = {}
|
|
26
|
+
extra_options['Prop'] = "Configuration=#{configuration}" if configuration
|
|
27
|
+
run_command 'pack', nuspec_or_project, extra_options
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def push(package, source)
|
|
31
|
+
run_command 'install', package, 'Source' => source
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def run_command(command, arguments, extra_options = nil)
|
|
37
|
+
options = @configuration['options'] || {}
|
|
38
|
+
options.merge!((@configuration['commands'] || {})[command] || {})
|
|
39
|
+
options.merge! extra_options if extra_options
|
|
40
|
+
output_dir = options['OutputDirectory']
|
|
41
|
+
FileUtils.makedirs output_dir if output_dir
|
|
42
|
+
call([command, arguments, options].flatten)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def format_option(name, value, switch)
|
|
46
|
+
switch ? "-#{name}" : "-#{name} #{encapsulate(value)}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'alpacabuildtool/tools/tool'
|
|
3
|
+
|
|
4
|
+
module AlpacaBuildTool
|
|
5
|
+
##
|
|
6
|
+
# NUnit provides access to nunit-console.exe tool
|
|
7
|
+
class NUnit < Tool
|
|
8
|
+
##
|
|
9
|
+
# Runs tests from project
|
|
10
|
+
#
|
|
11
|
+
# +project+:: project file with absolute path
|
|
12
|
+
# +debug+:: set to run test with debug configuration
|
|
13
|
+
def test(project, debug)
|
|
14
|
+
options = @configuration['options']
|
|
15
|
+
options['config'] = 'Debug' if debug
|
|
16
|
+
FileUtils.makedirs options['work'] if options['work']
|
|
17
|
+
FileUtils.makedirs File.dirname(options['output']) if options['output']
|
|
18
|
+
call([options, project])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def format_option(name, value, switch)
|
|
24
|
+
name = (name.to_s.length == 1 ? '-' : '--') + name.to_s
|
|
25
|
+
switch ? name : "#{name} #{encapsulate(value)}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'alpacabuildtool/tools/tool'
|
|
3
|
+
|
|
4
|
+
module AlpacaBuildTool
|
|
5
|
+
##
|
|
6
|
+
# NUnitOrange provides access to NUnitOrange.exe tool
|
|
7
|
+
class NUnitOrange < Tool
|
|
8
|
+
##
|
|
9
|
+
# Convert NUnit test results
|
|
10
|
+
def convert
|
|
11
|
+
input = @configuration['input']
|
|
12
|
+
return log.warn 'no nunit test results found' unless File.exist? input
|
|
13
|
+
FileUtils.makedirs File.dirname(@configuration['output'])
|
|
14
|
+
output = @configuration['output']
|
|
15
|
+
call([input, output])
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'alpacabuildtool/tools/wrapper'
|
|
3
|
+
|
|
4
|
+
module AlpacaBuildTool
|
|
5
|
+
##
|
|
6
|
+
# OpenCover provides access to OpenCover.exe tool
|
|
7
|
+
class OpenCover < Wrapper
|
|
8
|
+
##
|
|
9
|
+
# Runs coverage by running inner tool
|
|
10
|
+
#
|
|
11
|
+
# accepts &block for inner tool
|
|
12
|
+
#
|
|
13
|
+
# coverage_tool = package_manager.get('OpenCover', test_tool)
|
|
14
|
+
# coverage_tool.call do |tool|
|
|
15
|
+
# tool.test(project.file, debug)
|
|
16
|
+
# end
|
|
17
|
+
def call(&block)
|
|
18
|
+
options = @configuration.fetch('options')
|
|
19
|
+
FileUtils.makedirs File.dirname(options['output']) if options['output']
|
|
20
|
+
super([options], &block)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def format_option(name, value, switch)
|
|
26
|
+
switch ? "-#{name}" : "-#{name}:#{encapsulate(value)}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'alpacabuildtool/tools/tool'
|
|
3
|
+
|
|
4
|
+
module AlpacaBuildTool
|
|
5
|
+
##
|
|
6
|
+
# ReportGenerator provides access to ReportGenerator.exe tool
|
|
7
|
+
class ReportGenerator < Tool
|
|
8
|
+
##
|
|
9
|
+
# Convert OpenCover results
|
|
10
|
+
def convert
|
|
11
|
+
options = @configuration['options'] || {}
|
|
12
|
+
unless File.exist? options['reports']
|
|
13
|
+
return log.warn 'no coverage results found'
|
|
14
|
+
end
|
|
15
|
+
FileUtils.makedirs options['targetdir'] if options['targetdir']
|
|
16
|
+
call([options])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def format_option(name, value, switch)
|
|
22
|
+
switch ? "-#{name}" : "-#{name}:#{encapsulate(value)}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'mkmf'
|
|
2
|
+
require 'alpacabuildtool/log/log'
|
|
3
|
+
require 'English'
|
|
4
|
+
|
|
5
|
+
module AlpacaBuildTool
|
|
6
|
+
##
|
|
7
|
+
# Tool provides basic functionality for console tools
|
|
8
|
+
class Tool
|
|
9
|
+
include Log
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Creates an instance
|
|
13
|
+
# It check if configuration contains 'exe' which is executable
|
|
14
|
+
# If no then tries to find executable in PATH environment variable
|
|
15
|
+
# If not found then get exe from block passed
|
|
16
|
+
#
|
|
17
|
+
# +configuration+:: hash with tool configuration
|
|
18
|
+
# accepts &block with tool extended initialization if exe not found
|
|
19
|
+
#
|
|
20
|
+
# Tool.new config do
|
|
21
|
+
# exe_pattern = File.join(DOWNLOAD_DIR, '**', config['exe'])
|
|
22
|
+
# install(config['id'], DOWNLOAD_DIR, true)
|
|
23
|
+
# Dir.glob(exe_pattern).first # return executable
|
|
24
|
+
# end
|
|
25
|
+
def initialize(configuration)
|
|
26
|
+
@configuration = configuration.dup
|
|
27
|
+
@exe = @configuration['exe'] || ''
|
|
28
|
+
@exe = find_executable @exe unless File.executable? @exe
|
|
29
|
+
@exe = yield unless @exe || !block_given?
|
|
30
|
+
@exe = encapsulate(@exe) if @exe.to_s.include? ' '
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Execute tool in console with arguments
|
|
35
|
+
#
|
|
36
|
+
# +args+:: tool arguments
|
|
37
|
+
#
|
|
38
|
+
# tool.call(['file.cs', {c: true, type: 'test'}])
|
|
39
|
+
# # >> tool.exe file.cs /c /type:test
|
|
40
|
+
def call(args)
|
|
41
|
+
cmd = ([@exe] + format_arguments(args)).join ' '
|
|
42
|
+
log.info ">> #{cmd}\n"
|
|
43
|
+
execute cmd
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def format_arguments(arguments)
|
|
49
|
+
arguments.map do |argument|
|
|
50
|
+
case argument
|
|
51
|
+
when String then encapsulate argument
|
|
52
|
+
when Hash then flatten argument
|
|
53
|
+
else argument.to_s
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def encapsulate(object)
|
|
59
|
+
case object.to_s
|
|
60
|
+
when /^".* .*"$/ then object.to_s
|
|
61
|
+
when /^.* .*$/ then "\"#{object}\""
|
|
62
|
+
else object.to_s
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def flatten(argument)
|
|
67
|
+
argument.map do |key, value|
|
|
68
|
+
switch = value.nil? || value == true || value == false
|
|
69
|
+
format_option key, value, switch
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def format_option(name, value, switch)
|
|
74
|
+
switch ? "/#{name}" : "/#{name}:#{encapsulate(value)}"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def execute(cmd)
|
|
78
|
+
result = system cmd
|
|
79
|
+
fail "unknown command \"#{cmd}\"" if result.nil?
|
|
80
|
+
fail "call #{cmd}\nfailed: #{$CHILD_STATUS}" if result == false
|
|
81
|
+
result
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'alpacabuildtool/tools/tool'
|
|
2
|
+
|
|
3
|
+
module AlpacaBuildTool
|
|
4
|
+
##
|
|
5
|
+
# Wrapper represents console tools that execute other console tools inside
|
|
6
|
+
# their own process (like OpenCover, Ssh...)
|
|
7
|
+
class Wrapper < Tool
|
|
8
|
+
##
|
|
9
|
+
# Creates an instance
|
|
10
|
+
# Overrides Tool initialization by adding tool that should be executed later
|
|
11
|
+
#
|
|
12
|
+
# +configuration+:: wrapper tool configuration
|
|
13
|
+
# +tool+:: tool to be used inside wrapper tool
|
|
14
|
+
def initialize(configuration, tool)
|
|
15
|
+
super(configuration)
|
|
16
|
+
@tool = tool.dup
|
|
17
|
+
wrap_tool
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Execute wrapper tool with arguments
|
|
22
|
+
#
|
|
23
|
+
# +args+:: wrapper tool arguments
|
|
24
|
+
# requires &block to be executed against inner tool
|
|
25
|
+
#
|
|
26
|
+
# wrapper.call([debug: true]) do |tool|
|
|
27
|
+
# tool.call(['file.cs', {c: true, type: 'test'}])
|
|
28
|
+
# end
|
|
29
|
+
# # >> wrapper.exe /target:'tool.exe' /targetargs:'file.cs /c /type:test'
|
|
30
|
+
# # /debug
|
|
31
|
+
def call(args)
|
|
32
|
+
yield @tool
|
|
33
|
+
@target = encapsulate(@tool.exe)
|
|
34
|
+
@target_args = encapsulate(@tool.arguments)
|
|
35
|
+
super(args)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def wrap_tool
|
|
41
|
+
@tool.instance_eval do
|
|
42
|
+
def call(args)
|
|
43
|
+
@arguments = format_arguments(args).join ' '
|
|
44
|
+
end
|
|
45
|
+
self.class.__send__(:attr_reader, 'exe')
|
|
46
|
+
self.class.__send__(:attr_reader, 'arguments')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def format_arguments(arguments)
|
|
51
|
+
super arguments.map { |arg| detokenize_tool arg }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def detokenize_tool(object)
|
|
55
|
+
if object.is_a? String
|
|
56
|
+
return object.gsub('#{EXE}', @target).gsub('#{ARGS}', @target_args)
|
|
57
|
+
end
|
|
58
|
+
if object.is_a? Hash
|
|
59
|
+
object.keys.each do |key|
|
|
60
|
+
object[key] = detokenize_tool(object[key])
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
object
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module AlpacaBuildTool
|
|
4
|
+
# Version contains semantic version and methods
|
|
5
|
+
# for updating it
|
|
6
|
+
class Version
|
|
7
|
+
attr_reader :major, :minor, :patch, :special, :metadata, :file
|
|
8
|
+
attr_writer :metadata
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
# PreRelease acceptable tags
|
|
12
|
+
PRE_RELEASE = %w(alpha beta rc)
|
|
13
|
+
|
|
14
|
+
errors = %w(InvalidFile WrongDimension AlreadyPreRelease AlreadyRelease
|
|
15
|
+
FileNotFound MajorVersionNotInt MinorVersionNotInt
|
|
16
|
+
PatchVersionNotInt SpecialNotRecognized NotPreRelease
|
|
17
|
+
PreReleaseTagReachedFinalVersion)
|
|
18
|
+
errors.each { |error| const_set(error, Class.new(StandardError)) }
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Creates new instance
|
|
22
|
+
#
|
|
23
|
+
# +hash+:: Hash with version data:
|
|
24
|
+
# :file - file with path to .semver file
|
|
25
|
+
# :major - major version
|
|
26
|
+
# :minor - minor version
|
|
27
|
+
# :patch - patch version
|
|
28
|
+
# :special - special version
|
|
29
|
+
# :metadata - metadata
|
|
30
|
+
def initialize(hash)
|
|
31
|
+
@file = hash.fetch(:file) { fail InvalidFile }
|
|
32
|
+
@major = hash.fetch(:major) { fail InvalidFile }
|
|
33
|
+
@minor = hash.fetch(:minor) { fail InvalidFile }
|
|
34
|
+
@patch = hash.fetch(:patch) { fail InvalidFile }
|
|
35
|
+
@special = hash.fetch(:special) { fail InvalidFile }
|
|
36
|
+
@metadata = hash.fetch(:metadata) { fail InvalidFile }
|
|
37
|
+
validate
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
##
|
|
41
|
+
# Formatting version to string
|
|
42
|
+
#
|
|
43
|
+
# +format+:: format of version representation
|
|
44
|
+
# %M - Major
|
|
45
|
+
# %m - Minor
|
|
46
|
+
# %p - Patch
|
|
47
|
+
# %s - Special (adds '-')
|
|
48
|
+
# %d - Metadata (adds '+')
|
|
49
|
+
#
|
|
50
|
+
# v.inspect
|
|
51
|
+
# # => #<AlpacaBuildTool::Version:0x000000031aca90
|
|
52
|
+
# # @file="d:/Learning/Ruby/alpaca/.semver",
|
|
53
|
+
# # @major=1,
|
|
54
|
+
# # @minor=2,
|
|
55
|
+
# # @patch=3,
|
|
56
|
+
# # @special="rc",
|
|
57
|
+
# # @metadata="03fb4">
|
|
58
|
+
# v.format 'v%M.%m.%p%s%d'
|
|
59
|
+
# # => "v1.2.3-rc+03fb4"
|
|
60
|
+
def to_s(format = 'v%M.%m.%p%s%d')
|
|
61
|
+
result = format.gsub '%M', @major.to_s
|
|
62
|
+
result.gsub! '%m', @minor.to_s
|
|
63
|
+
result.gsub! '%p', @patch.to_s
|
|
64
|
+
result.gsub!('%s', prerelease? ? "-#{@special}" : '')
|
|
65
|
+
result.gsub!('%d', metadata? ? "+#{@metadata}" : '')
|
|
66
|
+
result
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Returns yaml representation that can be stored to .semver file
|
|
71
|
+
def to_yaml
|
|
72
|
+
YAML.dump(major: @major, minor: @minor, patch: @patch,
|
|
73
|
+
special: @special, metadata: @metadata)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# Returns true if #special isn't empty. Otherwise, false.
|
|
78
|
+
def prerelease?
|
|
79
|
+
!@special.nil? && !@special.empty?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# Returns true if #metadata isn't empty. Otherwise, false.
|
|
84
|
+
def metadata?
|
|
85
|
+
!@metadata.nil? && !@metadata.empty?
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Increase version following semantic version rules
|
|
90
|
+
#
|
|
91
|
+
# +dimension+:: one of the dimensions:
|
|
92
|
+
# :major # increase major and reset lower versions
|
|
93
|
+
# :minor # increase minor and reset lower versions
|
|
94
|
+
# :patch # increase patch and reset lower versions
|
|
95
|
+
# :prerelease # increase prerelease tag
|
|
96
|
+
def increase(dimension)
|
|
97
|
+
case dimension
|
|
98
|
+
when :major then increase_major
|
|
99
|
+
when :minor then increase_minor
|
|
100
|
+
when :patch then increase_patch
|
|
101
|
+
when :prerelease then increase_prerelease
|
|
102
|
+
else fail WrongDimension
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# Set version to prerelease by adding 'alpha' to special
|
|
108
|
+
def make_prerelease
|
|
109
|
+
fail AlreadyPreRelease if prerelease?
|
|
110
|
+
@special = PRE_RELEASE.first
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
##
|
|
114
|
+
# Clear special and metadata so version become higher and not prerelease
|
|
115
|
+
def release
|
|
116
|
+
fail AlreadyRelease unless prerelease?
|
|
117
|
+
@special = ''
|
|
118
|
+
@metadata = ''
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
def validate
|
|
124
|
+
fail FileNotFound unless File.exist?(@file)
|
|
125
|
+
fail MajorVersionNotInt unless @major.is_a?(Integer)
|
|
126
|
+
fail MinorVersionNotInt unless @minor.is_a?(Integer)
|
|
127
|
+
fail PatchVersionNotInt unless @patch.is_a?(Integer)
|
|
128
|
+
fail SpecialNotRecognized unless valid_special?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def valid_special?
|
|
132
|
+
!prerelease? || PRE_RELEASE.include?(@special)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def increase_major
|
|
136
|
+
@major += 1
|
|
137
|
+
@minor = 0
|
|
138
|
+
@patch = 0
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def increase_minor
|
|
142
|
+
@minor += 1
|
|
143
|
+
@patch = 0
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def increase_patch
|
|
147
|
+
@patch += 1
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def increase_prerelease
|
|
151
|
+
fail NotPreRelease unless prerelease?
|
|
152
|
+
tmp = ''
|
|
153
|
+
PRE_RELEASE.each do |version|
|
|
154
|
+
if @special == tmp
|
|
155
|
+
@special = version
|
|
156
|
+
return 0
|
|
157
|
+
end
|
|
158
|
+
tmp = version
|
|
159
|
+
end
|
|
160
|
+
fail PreReleaseTagReachedFinalVersion
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|