releasy 0.2.0rc1

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.
Files changed (74) hide show
  1. data/.gitignore +17 -0
  2. data/.yardopts +4 -0
  3. data/CHANGELOG.md +24 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +165 -0
  7. data/Rakefile +31 -0
  8. data/bin/7z.sfx +0 -0
  9. data/bin/releasy +7 -0
  10. data/lib/releasy.rb +18 -0
  11. data/lib/releasy/archivers.rb +12 -0
  12. data/lib/releasy/archivers/archiver.rb +74 -0
  13. data/lib/releasy/archivers/dmg.rb +18 -0
  14. data/lib/releasy/archivers/exe.rb +23 -0
  15. data/lib/releasy/archivers/seven_zip.rb +12 -0
  16. data/lib/releasy/archivers/tar_archiver.rb +14 -0
  17. data/lib/releasy/archivers/tar_bzip2.rb +13 -0
  18. data/lib/releasy/archivers/tar_gzip.rb +13 -0
  19. data/lib/releasy/archivers/zip.rb +12 -0
  20. data/lib/releasy/builders.rb +12 -0
  21. data/lib/releasy/builders/builder.rb +52 -0
  22. data/lib/releasy/builders/ocra_builder.rb +43 -0
  23. data/lib/releasy/builders/osx_app.rb +158 -0
  24. data/lib/releasy/builders/source.rb +27 -0
  25. data/lib/releasy/builders/windows_builder.rb +65 -0
  26. data/lib/releasy/builders/windows_folder.rb +47 -0
  27. data/lib/releasy/builders/windows_folder_from_ruby_dist.rb +150 -0
  28. data/lib/releasy/builders/windows_installer.rb +117 -0
  29. data/lib/releasy/builders/windows_standalone.rb +37 -0
  30. data/lib/releasy/cli.rb +12 -0
  31. data/lib/releasy/cli/install_sfx.rb +66 -0
  32. data/lib/releasy/dsl_wrapper.rb +71 -0
  33. data/lib/releasy/mixins/exec.rb +14 -0
  34. data/lib/releasy/mixins/has_archivers.rb +37 -0
  35. data/lib/releasy/mixins/has_gemspecs.rb +42 -0
  36. data/lib/releasy/mixins/register.rb +47 -0
  37. data/lib/releasy/project.rb +300 -0
  38. data/lib/releasy/version.rb +3 -0
  39. data/lib/releasy/windows_wrapper_maker.rb +90 -0
  40. data/lib/releasy/windows_wrapper_maker/Gemfile +8 -0
  41. data/media/releasy.png +0 -0
  42. data/releasy.gemspec +37 -0
  43. data/test/releasy/archivers_test.rb +65 -0
  44. data/test/releasy/builders/data/Info.plist +51 -0
  45. data/test/releasy/builders/data/Main.rb +12 -0
  46. data/test/releasy/builders/data/relapse_runner.rb +1 -0
  47. data/test/releasy/builders/data/set_app_executable.sh +3 -0
  48. data/test/releasy/builders/helpers/helper.rb +47 -0
  49. data/test/releasy/builders/ocra_builder_test.rb +37 -0
  50. data/test/releasy/builders/osx_app_test.rb +107 -0
  51. data/test/releasy/builders/source_test.rb +43 -0
  52. data/test/releasy/builders/windows_builder_test.rb +26 -0
  53. data/test/releasy/builders/windows_folder_from_ruby_dist_test.rb +105 -0
  54. data/test/releasy/builders/windows_folder_test.rb +56 -0
  55. data/test/releasy/builders/windows_installer_test.rb +62 -0
  56. data/test/releasy/builders/windows_standalone_test.rb +58 -0
  57. data/test/releasy/cli/install_sfx_test.rb +90 -0
  58. data/test/releasy/dsl_wrapper_test.rb +79 -0
  59. data/test/releasy/integration/source_test.rb +122 -0
  60. data/test/releasy/mixins/register_test.rb +52 -0
  61. data/test/releasy/project_test.rb +198 -0
  62. data/test/releasy/windows_wrapper_maker_test.rb +61 -0
  63. data/test/teststrap.rb +52 -0
  64. data/test/yard_test.rb +61 -0
  65. data/test_project/Gemfile +9 -0
  66. data/test_project/LICENSE.txt +1 -0
  67. data/test_project/README.txt +2 -0
  68. data/test_project/bin/test_app +3 -0
  69. data/test_project/lib/test_app.rb +6 -0
  70. data/test_project/lib/test_app/stuff.rb +1 -0
  71. data/test_project/test_app.icns +0 -0
  72. data/test_project/test_app.ico +0 -0
  73. data/wrappers/put_wrappers_here_for_testing.txt +17 -0
  74. metadata +236 -0
@@ -0,0 +1,14 @@
1
+ require "releasy/archivers/archiver"
2
+
3
+ module Releasy
4
+ module Archivers
5
+ # An archiver that tars and then compresses the folder.
6
+ # @abstract
7
+ class TarArchiver < Archiver
8
+ protected
9
+ def command(folder)
10
+ %[7z a -so -mmt -bd -ttar "#{folder}.tar" "#{folder}" | 7z a -si -bd -t#{self.class::FORMAT} -mx9 "#{folder}#{extension}"]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require "releasy/archivers/tar_archiver"
2
+
3
+ module Releasy
4
+ module Archivers
5
+ # Archives with tar and Bzip2 formats.
6
+ class TarBzip2 < TarArchiver
7
+ TYPE = :tar_bz2
8
+ DEFAULT_EXTENSION = ".tar.bz2"
9
+ FORMAT = "bzip2"
10
+ Archivers.register self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "releasy/archivers/tar_archiver"
2
+
3
+ module Releasy
4
+ module Archivers
5
+ # Archives with tar and Gzip formats.
6
+ class TarGzip < TarArchiver
7
+ TYPE = :tar_gz
8
+ DEFAULT_EXTENSION = ".tar.gz"
9
+ FORMAT = "gzip"
10
+ Archivers.register self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ require "releasy/archivers/archiver"
2
+
3
+ module Releasy
4
+ module Archivers
5
+ # Archives with zip format. This isn't efficient, but can be decompressed on Windows Vista or later without requiring a 3rd party tool.
6
+ class Zip < Archiver
7
+ TYPE = :zip
8
+ DEFAULT_EXTENSION = ".zip"
9
+ Archivers.register self
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'releasy/mixins/register'
2
+
3
+ module Releasy
4
+ # Contains all {Builder} types.
5
+ module Builders
6
+ extend Mixins::Register
7
+ end
8
+ end
9
+
10
+ %w[osx_app source windows_folder windows_folder_from_ruby_dist windows_installer windows_standalone].each do |builder|
11
+ require "releasy/builders/#{builder}"
12
+ end
@@ -0,0 +1,52 @@
1
+ require "releasy/mixins/has_archivers"
2
+ require "releasy/mixins/exec"
3
+
4
+ module Releasy
5
+ module Builders
6
+ # Builds release folders.
7
+ # @abstract
8
+ class Builder
9
+ include Rake::DSL
10
+ include Mixins::HasArchivers
11
+ include Mixins::Exec
12
+
13
+ # @return [Project] that this Builder belongs to.
14
+ attr_reader :project
15
+ # @return [String] Suffix on the folder generated, after name and version.
16
+ attr_accessor :folder_suffix
17
+
18
+ # @return [Symbol] Type of builder.
19
+ def type; self.class::TYPE; end
20
+
21
+ # Is the builder valid for the current platform (OS)?
22
+ def valid_for_platform?; true; end
23
+
24
+ def initialize(project)
25
+ super()
26
+ @project = project
27
+ @folder_suffix = self.class::DEFAULT_FOLDER_SUFFIX
28
+ setup
29
+ end
30
+
31
+ protected
32
+ # @return [String] Called from the project, but users don't need to know about it.
33
+ def task_group; type.to_s.split(/_/).first; end
34
+ # @return [String] Output folder.
35
+ def folder; "#{project.folder_base}#{folder_suffix.empty? ? '' : '_'}#{folder_suffix}"; end
36
+
37
+ protected
38
+ # Called by {#initalize}
39
+ def setup; end
40
+
41
+ protected
42
+ # Copy a number of files into a folder, maintaining relative paths.
43
+ def copy_files_relative(files, folder)
44
+ files.each do |file|
45
+ destination = File.join(folder, File.dirname(file))
46
+ mkdir_p destination unless File.exists? destination
47
+ cp file, destination
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,43 @@
1
+ require "releasy/builders/windows_builder"
2
+
3
+ module Releasy
4
+ module Builders
5
+ # Functionality for a {WindowsBuilder} that use Ocra and runs on Windows.
6
+ # @attr icon [String] Optional filename of icon to show on executable/installer (.ico).
7
+ # @abstract
8
+ class OcraBuilder < WindowsBuilder
9
+ OCRA_COMMAND = "ocra"
10
+ ICON_EXTENSION = ".ico"
11
+
12
+ # @return [String] Extra options to send to Ocra (Windows outputs only).
13
+ attr_accessor :ocra_parameters
14
+
15
+ def valid_for_platform?; Releasy.win_platform?; end
16
+
17
+ attr_reader :icon
18
+ def icon=(icon)
19
+ raise ArgumentError, "icon must be a #{ICON_EXTENSION} file" unless File.extname(icon) == ICON_EXTENSION
20
+ @icon = icon
21
+ end
22
+
23
+ protected
24
+ def setup
25
+ @icon = nil
26
+ @ocra_parameters = ""
27
+ super
28
+ end
29
+
30
+ protected
31
+ def ocra_command
32
+ command = defined?(Bundler) ? 'bundle exec ' : ''
33
+ command += %[#{OCRA_COMMAND} "#{project.executable}" ]
34
+ command += "--#{effective_executable_type} "
35
+ command += "--no-enc " if encoding_excluded?
36
+ command += "#{ocra_parameters} " if ocra_parameters
37
+ command += %[--icon "#{icon}" ] if icon
38
+ command += (project.files - [project.executable]).map {|f| %["#{f}"]}.join(" ")
39
+ command
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,158 @@
1
+ require "releasy/builders/builder"
2
+ require "releasy/mixins/has_gemspecs"
3
+
4
+ module Releasy
5
+ module Builders
6
+ # Builds an OS X application bundle.
7
+ #
8
+ # @attr icon [String] Optional filename of icon to show on executable/installer (.icns).
9
+ class OsxApp < Builder
10
+ include Mixins::HasGemspecs
11
+
12
+ TYPE = :osx_app
13
+
14
+ DEFAULT_FOLDER_SUFFIX = "OSX"
15
+
16
+ # Binary gems included in app.
17
+ BINARY_GEMS = %w[gosu texplay chipmunk]
18
+ # Icon type used in the app.
19
+ ICON_EXTENSION = ".icns"
20
+ # Source gems included in app that we should remove.
21
+ SOURCE_GEMS_TO_REMOVE = %w[chingu]
22
+
23
+ Builders.register self
24
+
25
+ # @return [String] Name of .app directory used as the framework for osx app release.
26
+ attr_accessor :wrapper
27
+ # @return [String] Inverse url of application (e.g. 'org.supergames.blasterbotsfrommars')
28
+ attr_accessor :url
29
+
30
+ # @return [String] Optional filename of icon to show on app (.icns).
31
+ attr_reader :icon
32
+
33
+ def icon=(icon)
34
+ raise ConfigError, "icon must be a #{ICON_EXTENSION} file" unless File.extname(icon) == ICON_EXTENSION
35
+ @icon = icon
36
+ end
37
+
38
+ protected
39
+ def generate_tasks
40
+ raise ConfigError, "#url not set" unless url
41
+ raise ConfigError, "#wrapper not set" unless wrapper
42
+ raise ConfigError, "#wrapper not valid wrapper: #{wrapper}" unless File.basename(wrapper) =~ /gosu-mac-wrapper-[\d\.]+.tar.gz/
43
+
44
+ new_app = File.join folder, app_name
45
+
46
+ directory folder
47
+
48
+ desc "Build OS X app"
49
+ task "build:osx:app" => folder
50
+
51
+ file folder => project.files + [wrapper] do
52
+ Rake::FileUtilsExt.verbose project.verbose?
53
+
54
+ # Copy the app files.
55
+ exec %[7z x -so -bd "#{wrapper}" | 7z x -si -mmt -bd -ttar -o"#{folder}"]
56
+ mv File.join(folder, "RubyGosu App.app"), new_app
57
+
58
+ ## Copy my source files.
59
+ copy_files_relative project.files, File.join(new_app, 'Contents/Resources/application')
60
+
61
+ # Copy accompanying files.
62
+ project.exposed_files.each {|file| cp file, folder }
63
+
64
+ copy_gems vendored_gem_names(BINARY_GEMS), File.join(new_app, 'Contents/Resources/vendor')
65
+ create_main new_app
66
+ edit_init new_app
67
+ remove_gems new_app
68
+ rename_executable new_app
69
+ update_icon new_app
70
+ create_executable_setter
71
+ end
72
+ end
73
+
74
+ protected
75
+ def setup
76
+ @icon = nil
77
+ @url = nil
78
+ @wrapper = nil
79
+ super
80
+ end
81
+
82
+ protected
83
+ def app_name; "#{project.name}.app"; end
84
+
85
+ protected
86
+ def create_executable_setter
87
+ if Releasy.win_platform?
88
+ # Ensure that we have a Unixy file by setting binary ("wb") mode on Windows.
89
+ File.open(File.join(folder, "set_app_executable.sh"), "wb") do |file|
90
+ file.puts <<END
91
+ #!/bin/sh
92
+ chmod a+x "./#{app_name}/Contents/MacOS/#{project.name}"
93
+ echo "Made #{app_name} executable"
94
+ END
95
+
96
+ end
97
+ end
98
+ end
99
+
100
+ protected
101
+ def rename_executable(app)
102
+ new_executable = "#{app}/Contents/MacOS/#{project.name}"
103
+ mv "#{app}/Contents/MacOS/RubyGosu App" , new_executable
104
+ chmod 0755, new_executable
105
+ end
106
+
107
+ protected
108
+ # Remove unnecessary gems from the distribution.
109
+ def remove_gems(app)
110
+ SOURCE_GEMS_TO_REMOVE.each do |gem|
111
+ rm_r "#{app}/Contents/Resources/lib/#{gem}"
112
+ end
113
+ end
114
+
115
+ protected
116
+ def update_icon(app)
117
+ if icon
118
+ rm "#{app}/Contents/Resources/Gosu.icns"
119
+ cp icon, "#{app}/Contents/Resources"
120
+ end
121
+ end
122
+
123
+ protected
124
+ def create_main(app)
125
+ # Something for the .app to run -> just a little redirection file.
126
+ puts "--- Creating Main.rb" if project.verbose?
127
+ File.open("#{app}/Contents/Resources/Main.rb", "w") do |file|
128
+ file.puts <<END_TEXT
129
+ Dir[File.expand_path("../vendor/gems/*/lib", __FILE__)].each do |lib|
130
+ $LOAD_PATH.unshift lib
131
+ end
132
+
133
+ OSX_EXECUTABLE_FOLDER = File.expand_path("../../..", __FILE__)
134
+
135
+ # Really hacky fudge-fix for something oddly missing in the .app.
136
+ class Encoding
137
+ UTF_7 = UTF_16BE = UTF_16LE = UTF_32BE = UTF_32LE = Encoding.list.first
138
+ end
139
+
140
+ load 'application/#{project.executable}'
141
+ END_TEXT
142
+ end
143
+ end
144
+
145
+ protected
146
+ def edit_init(app)
147
+ file = "#{app}/Contents/Info.plist"
148
+ # Edit the info file to be specific for my game.
149
+ puts "--- Editing init" if project.verbose?
150
+ info = File.read(file)
151
+ info.sub!('<string>Gosu</string>', "<string>#{File.basename(icon).chomp(File.extname(icon))}</string>") if icon
152
+ info.sub!('<string>RubyGosu App</string>', "<string>#{project.name}</string>")
153
+ info.sub!('<string>org.libgosu.UntitledGame</string>', "<string>#{url}</string>")
154
+ File.open(file, "w") {|f| f.puts info }
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,27 @@
1
+ require "releasy/builders/builder"
2
+
3
+ module Releasy
4
+ module Builders
5
+ # Creates a folder containing the application source.
6
+ class Source < Builder
7
+ TYPE = :source
8
+ Builders.register self
9
+
10
+ DEFAULT_FOLDER_SUFFIX = "SOURCE"
11
+
12
+ protected
13
+ def generate_tasks
14
+ desc "Build source folder"
15
+ task "build:source" => folder
16
+
17
+ directory folder
18
+
19
+ file folder => project.files do
20
+ Rake::FileUtilsExt.verbose project.verbose?
21
+
22
+ copy_files_relative project.files, folder
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,65 @@
1
+ require "releasy/builders/builder"
2
+
3
+ module Releasy
4
+ module Builders
5
+ # General functionality for Windows builders.
6
+ # @abstract
7
+ # @attr icon [String] Optional filename of icon to show on executable/installer (.ico).
8
+ class WindowsBuilder < Builder
9
+ EXECUTABLE_TYPES = [:auto, :windows, :console]
10
+
11
+ # @return [:auto, :windows, :console] Type of ruby to run executable with. :console means run with 'ruby.exe', :windows means run with 'rubyw.exe', :auto means determine type from executable extension (.rb => :console or .rbw => :windows).
12
+ attr_accessor :executable_type
13
+
14
+ # Excludes encoding files from 1.9 releases (equivalent to using '--no-enc' in Ocra).
15
+ def exclude_encoding
16
+ @exclude_encoding = true
17
+ end
18
+
19
+ # Should encoding files be excluded?
20
+ def encoding_excluded?; @exclude_encoding; end
21
+ protected :encoding_excluded?
22
+
23
+ # Executable type, resolving :auto if possible.
24
+ # @return [:windows, :console]
25
+ def effective_executable_type
26
+ if executable_type == :auto
27
+ case File.extname(project.executable)
28
+ when '.rbw'
29
+ :windows
30
+ when '.rb'
31
+ :console
32
+ else
33
+ raise ConfigError, "Unless the executable file extension is .rbw or .rb, then #executable_type must be explicitly :windows or :console"
34
+ end
35
+ else
36
+ executable_type
37
+ end
38
+ end
39
+
40
+ protected
41
+ def setup
42
+ @exclude_encoding = false
43
+ @executable_type = :auto
44
+ super
45
+ end
46
+
47
+ protected
48
+ def create_link_files(dir)
49
+ project.send(:links).each_pair do |url, title|
50
+ create_link_file url, File.join(dir, title)
51
+ end
52
+ end
53
+
54
+ protected
55
+ def create_link_file(url, title)
56
+ File.open("#{title}.url", "w") do |file|
57
+ file.puts <<END
58
+ [InternetShortcut]
59
+ URL=#{url}
60
+ END
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,47 @@
1
+ require "releasy/builders/ocra_builder"
2
+ require 'releasy/windows_wrapper_maker'
3
+
4
+ module Releasy
5
+ module Builders
6
+ # Builds a folder containing Ruby + your source + a small Windows executable to run your executable script.
7
+ class WindowsFolder < OcraBuilder
8
+ TYPE = :windows_folder
9
+ DEFAULT_FOLDER_SUFFIX = "WIN32"
10
+
11
+ Builders.register self
12
+
13
+ protected
14
+ # FOLDER containing EXE, Ruby + source.
15
+ def generate_tasks
16
+ directory project.output_path
17
+
18
+ file folder => project.files do
19
+ Rake::FileUtilsExt.verbose project.verbose?
20
+
21
+ tmp_ocra_executable = "#{folder}.exe"
22
+
23
+ exec %[#{ocra_command} --output "#{tmp_ocra_executable}" --debug-extract]
24
+
25
+ # Extract the files from the executable.
26
+ system tmp_ocra_executable
27
+ rm tmp_ocra_executable
28
+
29
+ mv Dir["#{File.dirname(folder)}/ocr*\.tmp"].first, folder
30
+
31
+ maker = Releasy::WindowsWrapperMaker.new
32
+ maker.build_executable("#{folder}/#{executable_name}", "src/#{project.executable}",
33
+ :icon => icon, :windows => (effective_executable_type == :windows))
34
+
35
+ create_link_files folder
36
+ project.exposed_files.each {|file| cp file, folder }
37
+ end
38
+
39
+ desc "Build source/exe folder #{project.version}"
40
+ task "build:windows:folder" => folder
41
+ end
42
+
43
+ protected
44
+ def executable_name; "#{project.underscored_name}.exe"; end
45
+ end
46
+ end
47
+ end