shoes-package 4.0.0.pre3

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e85a08b46b6fcdaa86a5b1609c14fb2e58c08677
4
+ data.tar.gz: b655bde5a2d94c020ed7a99a7eed8337cbb36d2f
5
+ SHA512:
6
+ metadata.gz: d425a176814a1adfb819ed1296ad7d5f4308ce13b5928bdbbe933ad99a87c82714f179e37a2b2f5c22abcb43d052ef00d01e153d3f4ccdb54481b99351a4707c
7
+ data.tar.gz: 31d06640d06a1932e8826727d62720d499b9a1ae391a611818d98607d6aada43dc98b7fd4f4b6b7d903c2753bfeb7472b5a578b47d92a61afb0609e83a2e4ff1
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,156 @@
1
+ require 'pathname'
2
+ require 'yaml'
3
+ require 'furoshiki/configuration'
4
+ require 'furoshiki/validator'
5
+ require 'furoshiki/warbler_extensions'
6
+ require 'warbler/traits/shoes'
7
+
8
+ class Shoes
9
+ module Package
10
+ # Configuration for Shoes packagers.
11
+ #
12
+ # @example
13
+ # config_file = '/path/to/app.yaml'
14
+ # config = Shoes::Package::Configuration.load(config_file)
15
+ #
16
+ module Configuration
17
+ extend ::Furoshiki::Util
18
+
19
+ JAR_APP_TEMPLATE_URL = 'https://s3.amazonaws.com/net.wasnotrice.shoes/wrappers/shoes-app-template-0.0.1.zip'
20
+
21
+ # Convenience method for loading config from a file. Note that you
22
+ # can pass four kinds of paths to the loader. Given the following
23
+ # file structure:
24
+ #
25
+ # ├── a
26
+ # │   ├── app.yaml
27
+ # │   └── shoes-app-a.rb
28
+ # └── b
29
+ # └── shoes-app-b.rb
30
+ #
31
+ # To package an app that has an `app.yaml`, like `shoes-app-a.rb`,
32
+ # you can call the loader with any of:
33
+ #
34
+ # - a/app.yaml
35
+ # - a
36
+ # - a/shoes-app-a.rb
37
+ #
38
+ # These will all find and use your configuration in `a/app.yaml`.
39
+ # To package an app that does not have an `app.yaml`, like
40
+ # `b/shoes-app-b.rb`, you must call the loader with the path of
41
+ # the script itself. Note that without an `app.yaml`, you will
42
+ # only bundle a single file, and your app will simply use the
43
+ # Shoes app icon.
44
+ #
45
+ # @overload load(path, base_config)
46
+ # @param [String] path location of the app's 'app.yaml'
47
+ # @param [Hash] base_config default values
48
+ # @overload load(path)
49
+ # @param [String] path location of the directory that
50
+ # contains the app's 'app.yaml'
51
+ # @param [Hash] base_config default values
52
+ # @overload load(path)
53
+ # @param [String] path location of the app
54
+ # @param [Hash] base_config default values
55
+ def self.load(path, base_config = {})
56
+ pathname = Pathname.new(path)
57
+ app_yaml = Pathname.new('app.yaml')
58
+
59
+ if pathname.basename == app_yaml
60
+ file, dir = pathname, pathname.dirname
61
+ elsif pathname.directory?
62
+ file, dir = pathname.join(app_yaml), pathname
63
+ elsif pathname.file? && pathname.parent.children.include?(pathname.parent.join app_yaml)
64
+ file, dir = pathname.parent.join(app_yaml), pathname.parent
65
+ else
66
+ file, dir = config_for_single_file_app(pathname)
67
+ end
68
+
69
+ config = YAML.load(file.read)
70
+ config[:working_dir] = dir
71
+ config[:gems] = merge_gems(base_config, config)
72
+ create(config)
73
+ end
74
+
75
+ # @param [Hash] config user options
76
+ def self.create(config = {})
77
+ defaults = {
78
+ name: 'Shoes App',
79
+ version: '0.0.0',
80
+ release: 'Rookie',
81
+ run: nil,
82
+ ignore: 'pkg',
83
+ # TODO: Add actual paths. Keep these keys for compatibility with Shoes 3
84
+ icons: {
85
+ #osx: 'path/to/default/App.icns',
86
+ #gtk: 'path/to/default/app.png',
87
+ #win32: 'path/to/default/App.ico',
88
+ },
89
+ # TODO: Add actual paths. Keep these keys for compatibility with Shoes 3
90
+ dmg: {
91
+ #ds_store: 'path/to/default/.DS_Store',
92
+ #background: 'path/to/default/background.png'
93
+ },
94
+ working_dir: Dir.pwd,
95
+ gems: ['shoes-core'],
96
+ validator: Validator,
97
+ warbler_extensions: WarblerExtensions
98
+ }
99
+
100
+ symbolized_config = deep_symbolize_keys(config)
101
+ symbolized_config[:gems] = merge_gems(defaults, symbolized_config)
102
+ Furoshiki::Configuration.new defaults.merge(symbolized_config)
103
+ end
104
+
105
+ private
106
+ # If it exists, load default options. If not, let the filesystem raise an
107
+ # error.
108
+ def self.config_for_single_file_app(pathname)
109
+ default_options = {
110
+ run: pathname.basename.to_s,
111
+ name: pathname.basename(pathname.extname).to_s.gsub(/\W/, '-')
112
+ }.to_yaml
113
+ options = pathname.exist? ? default_options : pathname
114
+ dummy_file = Struct.new(:read)
115
+ [dummy_file.new(options), pathname.parent]
116
+ end
117
+
118
+ # We want to retain all of the gems, but simply merging the hash will
119
+ # replace the whole array, so we handle the gems separately. Note that
120
+ # keys may not have been symbolized yet
121
+ def self.merge_gems(base, additional)
122
+ base_gems = base.fetch(:gems) rescue base['gems']
123
+ additional_gems = additional.fetch(:gems) rescue additional['gems']
124
+ Array(base_gems).concat(Array(additional_gems)).uniq
125
+ end
126
+ end
127
+
128
+ class Validator < Furoshiki::Validator
129
+ def validate
130
+ unless config.run && config.working_dir.join(config.run).exist?
131
+ add_missing_file_error(config.run, "Run file")
132
+ end
133
+
134
+ if config.icons[:osx] && !config.working_dir.join(config.icons[:osx]).exist?
135
+ add_missing_file_error(config.icons[:osx], "OS X icon file")
136
+ end
137
+ end
138
+ end
139
+
140
+ class WarblerExtensions < Furoshiki::WarblerExtensions
141
+ def customize(warbler_config)
142
+ warbler_config.tap do |warbler|
143
+ warbler.pathmaps.application = ['shoes-app/%p']
144
+ warbler.extend ShoesWarblerConfig
145
+ warbler.run = @config.run.split(/\s/).first
146
+ end
147
+ end
148
+
149
+ private
150
+ # Adds Shoes-specific functionality to the Warbler Config
151
+ module ShoesWarblerConfig
152
+ attr_accessor :run
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,17 @@
1
+ require 'forwardable'
2
+ require 'furoshiki/jar'
3
+
4
+ class Shoes
5
+ module Package
6
+ class Jar
7
+ extend Forwardable
8
+
9
+ def_delegators :@packager, :package, :default_dir, :filename
10
+
11
+ def initialize(config)
12
+ config.gems << 'shoes-swt'
13
+ @packager = Furoshiki::Jar.new(config)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require 'forwardable'
2
+ require 'furoshiki/jar_app'
3
+
4
+ class Shoes
5
+ module Package
6
+ class JarApp
7
+ extend Forwardable
8
+
9
+ def_delegators :@packager, :package, :default_package_dir, :cache_dir,
10
+ :remote_template_url, :template_path
11
+
12
+ def initialize(config)
13
+ config.gems << 'shoes-swt'
14
+ @packager = Furoshiki::JarApp.new(config)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ class Shoes
2
+ module Package
3
+ VERSION = "4.0.0.pre3"
4
+ end
5
+ end
@@ -0,0 +1,53 @@
1
+ require 'warbler'
2
+ require 'warbler/traits'
3
+ require 'warbler/traits/furoshiki'
4
+
5
+ module Warbler
6
+ module Traits
7
+ # Hack to control the executable
8
+ class NoGemspec
9
+ def update_archive(jar); end
10
+ end
11
+
12
+ # Disable this trait, since we are subclassing it (don't run twice)
13
+ class Furoshiki
14
+ def self.detect?; false; end
15
+ end
16
+
17
+ class Shoes < Furoshiki
18
+ def self.detect?
19
+ true
20
+ end
21
+
22
+ def self.requires?(trait)
23
+ # Actually, it would be better to dump the NoGemspec trait, but since
24
+ # we can't do that, we can at least make sure that this trait gets
25
+ # processed later by declaring that it requires NoGemspec.
26
+ [Traits::Jar, Traits::NoGemspec].include? trait
27
+ end
28
+
29
+ def after_configure
30
+ config.init_contents << StringIO.new("require 'shoes'\nShoes.configuration.backend = :swt\n")
31
+ end
32
+
33
+ def update_archive(jar)
34
+ super
35
+ add_main_rb(jar, apply_pathmaps(config, default_executable, :application))
36
+ end
37
+
38
+ # Uses the `@config.run` if it exists. Otherwise, looks in the
39
+ # application's `bin` directory for an executable with the same name as
40
+ # the jar. If this also fails, defaults to the first executable (alphabetically) in the
41
+ # applications `bin` directory.
42
+ #
43
+ # @return [String] filename of the executable to run
44
+ def default_executable
45
+ return @config.run if @config.run
46
+ exes = Dir['bin/*'].sort
47
+ exe = exes.grep(/#{config.jar_name}/).first || exes.first
48
+ raise "No executable script found" unless exe
49
+ exe
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('lib/shoes/package/version')
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "shoes-package"
6
+ s.version = Shoes::Package::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Team Shoes"]
9
+ s.email = ["shoes@librelist.com"]
10
+ s.homepage = "https://github.com/shoes/shoes4"
11
+ s.summary = %q{Application packaging for Shoes, the best little GUI toolkit for Ruby.}
12
+ s.description = %q{Application packaging for Shoes, the best little GUI toolkit for Ruby. Shoes makes building for Mac, Windows, and Linux super simple.}
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files`.split($/)
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency "shoes-core", Shoes::Package::VERSION
20
+ s.add_dependency "furoshiki", "~> 0.3.0"
21
+ end
@@ -0,0 +1,207 @@
1
+ require_relative 'spec_helper'
2
+ require 'shoes/package/configuration'
3
+
4
+ describe Shoes::Package::Configuration do
5
+ context "defaults" do
6
+ subject { Shoes::Package::Configuration.create }
7
+
8
+ its(:name) { should eq('Shoes App') }
9
+ its(:shortname) { should eq('shoesapp') }
10
+ its(:ignore) { should eq(['pkg']) }
11
+ its(:gems) { should include('shoes-core') }
12
+ its(:version) { should eq('0.0.0') }
13
+ its(:release) { should eq('Rookie') }
14
+ its(:icons) { should be_an_instance_of(Hash) }
15
+ its(:dmg) { should be_an_instance_of(Hash) }
16
+ its(:run) { should be_nil }
17
+ its(:working_dir) { should eq(Pathname.new(Dir.pwd)) }
18
+ it { is_expected.not_to be_valid } # no :run
19
+
20
+ # TODO: Implement
21
+ describe "#icons" do
22
+ it 'osx is nil' do
23
+ expect(subject.icons[:osx]).to be_nil
24
+ end
25
+
26
+ it 'gtk is nil' do
27
+ expect(subject.icons[:gtk]).to be_nil
28
+ end
29
+
30
+ it 'win32 is nil' do
31
+ expect(subject.icons[:win32]).to be_nil
32
+ end
33
+ end
34
+
35
+ # TODO: Implement
36
+ describe "#dmg" do
37
+ it "ds_store is nil" do
38
+ expect(subject.dmg[:ds_store]).to be_nil
39
+ end
40
+
41
+ it "background is nil" do
42
+ expect(subject.dmg[:background]).to be_nil
43
+ end
44
+ end
45
+
46
+ describe "#to_hash" do
47
+ it "round-trips" do
48
+ expect(Shoes::Package::Configuration.create(subject.to_hash)).to eq(subject)
49
+ end
50
+ end
51
+ end
52
+
53
+ context "with options" do
54
+ include_context 'config'
55
+ subject { Shoes::Package::Configuration.load(@config_filename) }
56
+
57
+ its(:name) { should eq('Sugar Clouds') }
58
+ its(:shortname) { should eq('sweet-nebulae') }
59
+ its(:ignore) { should include('pkg') }
60
+ its(:run) { should eq('bin/hello_world') }
61
+ its(:gems) { should include('rspec') }
62
+ its(:gems) { should include('shoes-core') }
63
+ its(:version) { should eq('0.0.1') }
64
+ its(:release) { should eq('Mindfully') }
65
+ its(:icons) { should be_an_instance_of(Hash) }
66
+ its(:dmg) { should be_an_instance_of(Hash) }
67
+ its(:working_dir) { should eq(@config_filename.dirname) }
68
+ it { is_expected.to be_valid }
69
+
70
+ describe "#icons" do
71
+ it 'has osx' do
72
+ expect(subject.icons[:osx]).to eq('img/boots.icns')
73
+ end
74
+
75
+ it 'has gtk' do
76
+ expect(subject.icons[:gtk]).to eq('img/boots_512x512x32.png')
77
+ end
78
+
79
+ it 'has win32' do
80
+ expect(subject.icons[:win32]).to eq('img/boots.ico')
81
+ end
82
+ end
83
+
84
+ describe "#dmg" do
85
+ it "has ds_store" do
86
+ expect(subject.dmg[:ds_store]).to eq('path/to/custom/.DS_Store')
87
+ end
88
+
89
+ it "has background" do
90
+ expect(subject.dmg[:background]).to eq('path/to/custom/background.png')
91
+ end
92
+ end
93
+
94
+ it "incorporates custom features" do
95
+ expect(subject.custom).to eq('my custom feature')
96
+ end
97
+
98
+ it "round-trips" do
99
+ expect(Shoes::Package::Configuration.create(subject.to_hash)).to eq(subject)
100
+ end
101
+ end
102
+
103
+ context "with name, but without explicit shortname" do
104
+ let(:options) { {:name => "Sugar Clouds"} }
105
+ subject { Shoes::Package::Configuration.create options }
106
+
107
+ its(:name) { should eq("Sugar Clouds") }
108
+ its(:shortname) { should eq("sugarclouds") }
109
+ end
110
+
111
+ context "when the file to run doens't exist" do
112
+ let(:options) { {:run => "path/to/non-existent/file"} }
113
+ subject { Shoes::Package::Configuration.create options }
114
+
115
+ it { is_expected.not_to be_valid }
116
+ end
117
+
118
+ context "when osx icon is not specified" do
119
+ include_context 'config'
120
+ let(:valid_config) { Shoes::Package::Configuration.load(@config_filename) }
121
+ let(:options) { valid_config.to_hash.merge(:icons => {}) }
122
+ subject { Shoes::Package::Configuration.create(options) }
123
+
124
+ it "sets osx icon path to nil" do
125
+ expect(subject.icons[:osx]).to be_nil
126
+ end
127
+
128
+ it "is valid" do
129
+ expect(subject).to be_valid
130
+ end
131
+ end
132
+
133
+ context "when osx icon is specified, but doesn't exist" do
134
+ let(:options) { ({:icons => {:osx => "path/to/non-existent/file"}}) }
135
+ subject { Shoes::Package::Configuration.create options }
136
+
137
+ it "sets osx icon path" do
138
+ expect(subject.icons[:osx]).to eq("path/to/non-existent/file")
139
+ end
140
+
141
+ it { is_expected.not_to be_valid }
142
+ end
143
+
144
+ context "auto-loading" do
145
+ include_context 'config'
146
+
147
+ shared_examples "config with path" do
148
+ it "finds the config" do
149
+ Dir.chdir File.dirname(__FILE__) do
150
+ config = Shoes::Package::Configuration.load(path)
151
+ expect(config.shortname).to eq('sweet-nebulae')
152
+ end
153
+ end
154
+ end
155
+
156
+ context "with an 'app.yaml'" do
157
+ let(:path) { @config_filename }
158
+ it_behaves_like "config with path"
159
+ end
160
+
161
+ context "with a path to a directory containing an 'app.yaml'" do
162
+ let(:path) { @config_filename.parent }
163
+ it_behaves_like "config with path"
164
+ end
165
+
166
+ context "with a path to a file that is siblings with an 'app.yaml'" do
167
+ let(:path) { @config_filename.parent.join('sibling.rb') }
168
+ it_behaves_like "config with path"
169
+ end
170
+
171
+ context "with a path that exists, but no 'app.yaml'" do
172
+ let(:path) { @config_filename.parent.join('bin/hello_world') }
173
+ subject { Shoes::Package::Configuration.load(path) }
174
+
175
+ its(:name) { should eq('hello_world') }
176
+ its(:shortname) { should eq('hello_world') }
177
+ end
178
+
179
+ context "when the file doesn't exist" do
180
+ it "blows up" do
181
+ expect { Shoes::Package::Configuration.load('some/bogus/path') }.to raise_error
182
+ end
183
+ end
184
+
185
+ context "with additional gems" do
186
+ let(:path) { @config_filename }
187
+ let(:additional_config) { { gems: gems } }
188
+ let(:config) { config = Shoes::Package::Configuration.load(path, additional_config) }
189
+
190
+ context "one gem" do
191
+ let(:gems) { 'shoes-swt' }
192
+
193
+ it "adds one additional" do
194
+ expect(config.gems).to include('shoes-swt')
195
+ end
196
+ end
197
+
198
+ context "multiple gems" do
199
+ let(:gems) { ['shoes-swt', 'shoes-extras'] }
200
+
201
+ it "adds multiple additional gems" do
202
+ expect(config.gems & gems).to eq(gems)
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,69 @@
1
+ # Packaging caches files in $HOME/.furoshiki/cache by default.
2
+ # For testing, we override $HOME using $FUROSHIKI_HOME
3
+ FUROSHIKI_SPEC_DIR = Pathname.new(__FILE__).dirname.expand_path.to_s
4
+ ENV['FUROSHIKI_HOME'] = FUROSHIKI_SPEC_DIR
5
+
6
+ SHOES_PACKAGE_SPEC_ROOT= File.expand_path('..', __FILE__)
7
+
8
+ $LOAD_PATH << File.expand_path(SHOES_PACKAGE_SPEC_ROOT)
9
+ $LOAD_PATH << File.expand_path('../../lib', __FILE__)
10
+ $LOAD_PATH << File.expand_path('../../../shoes-core/lib', __FILE__)
11
+
12
+ require 'pathname'
13
+ require 'rspec/its'
14
+
15
+ Dir["#{SHOES_PACKAGE_SPEC_ROOT}/support/**/*.rb"].each {|f| require f}
16
+
17
+ module PackageHelpers
18
+ # need these values from a context block, so let doesn't work
19
+ def spec_dir
20
+ Pathname.new(__FILE__).join('..').cleanpath
21
+ end
22
+
23
+ def input_dir
24
+ spec_dir.join 'support', 'zip'
25
+ end
26
+ end
27
+
28
+ # Guards for running or not running specs. Specs in the guarded block only
29
+ # run if the guard conditions are met.
30
+ #
31
+ module Guard
32
+ # Runs specs only if platform matches
33
+ #
34
+ # @example
35
+ # platform_is :windows do
36
+ # it "does something only on windows" do
37
+ # # specification
38
+ # end
39
+ # end
40
+ def platform_is(platform)
41
+ yield if self.send "platform_is_#{platform.to_s}"
42
+ end
43
+
44
+ # Runs specs only if platform does not match
45
+ #
46
+ # @example
47
+ # platform_is_not :windows do
48
+ # it "does something only on posix systems" do
49
+ # # specification
50
+ # end
51
+ # end
52
+ def platform_is_not(platform)
53
+ yield unless self.send "platform_is_#{platform.to_s}"
54
+ end
55
+
56
+ def platform_is_windows
57
+ return RbConfig::CONFIG['host_os'] =~ /windows|mswin/i
58
+ end
59
+
60
+ def platform_is_linux
61
+ return RbConfig::CONFIG['host_os'] =~ /linux/i
62
+ end
63
+
64
+ def platform_is_osx
65
+ return RbConfig::CONFIG['host_os'] =~ /darwin/i
66
+ end
67
+ end
68
+
69
+ include Guard
@@ -0,0 +1,15 @@
1
+ require 'yaml'
2
+ require 'pathname'
3
+
4
+ shared_context 'config' do
5
+ before :all do
6
+ @config_filename = Pathname.new(__FILE__).join('../../test_app/app.yaml').cleanpath
7
+ end
8
+ end
9
+
10
+ shared_context 'package' do
11
+ before :all do
12
+ @app_dir = Pathname.new(__FILE__).join '../../test_app'
13
+ @output_dir = @app_dir.join 'pkg'
14
+ end
15
+ end
@@ -0,0 +1,131 @@
1
+ require_relative 'spec_helper'
2
+ require 'shoes/package/configuration'
3
+ require 'shoes/package/jar_app'
4
+
5
+ include PackageHelpers
6
+
7
+ describe Shoes::Package::JarApp do
8
+ include_context 'config'
9
+ include_context 'package'
10
+
11
+ let(:config) { Shoes::Package::Configuration.load @config_filename }
12
+ subject { Shoes::Package::JarApp.new config }
13
+
14
+ let(:launcher) { @output_file.join('Contents/MacOS/JavaAppLauncher') }
15
+ let(:icon) { @output_file.join('Contents/Resources/boots.icns') }
16
+ let(:jar) { @output_file.join('Contents/Java/sweet-nebulae.jar') }
17
+
18
+ # $FUROSHIKI_HOME is set in spec_helper.rb for testing purposes,
19
+ # but should default to $HOME
20
+ context "when not setting $FUROSHIKI_HOME" do
21
+ before do
22
+ @old_furoshiki_home = ENV['FUROSHIKI_HOME']
23
+ ENV['FUROSHIKI_HOME'] = nil
24
+ end
25
+
26
+
27
+ its(:cache_dir) { should eq(Pathname.new(Dir.home).join('.furoshiki', 'cache')) }
28
+
29
+ after do
30
+ ENV['FUROSHIKI_HOME'] = @old_furoshiki_home
31
+ end
32
+ end
33
+
34
+ context "default" do
35
+ let(:cache_dir) { Pathname.new(SHOES_PACKAGE_SPEC_ROOT).join('.furoshiki', 'cache') }
36
+ its(:cache_dir) { should eq(cache_dir) }
37
+
38
+ it "sets package dir to {pwd}/pkg" do
39
+ Dir.chdir @app_dir do
40
+ expect(subject.default_package_dir).to eq(@app_dir.join 'pkg')
41
+ end
42
+ end
43
+
44
+ its(:template_path) { should eq(cache_dir.join('shoes-app-template.zip')) }
45
+ its(:remote_template_url) { should eq(Shoes::Package::Configuration::JAR_APP_TEMPLATE_URL) }
46
+ end
47
+
48
+ context "when creating a .app" do
49
+ before :all do
50
+ @output_dir.rmtree if @output_dir.exist?
51
+ @output_dir.mkpath
52
+ app_name = 'Sugar Clouds.app'
53
+ @output_file = @output_dir.join app_name
54
+ config = Shoes::Package::Configuration.load @config_filename
55
+ @subject = Shoes::Package::JarApp.new config
56
+ @subject.package
57
+ end
58
+
59
+ subject { @subject }
60
+
61
+ its(:template_path) { should exist }
62
+
63
+ it "creates a .app" do
64
+ expect(@output_file).to exist
65
+ end
66
+
67
+ it "includes launcher" do
68
+ expect(launcher).to exist
69
+ end
70
+
71
+ # Windows can't test this
72
+ platform_is_not :windows do
73
+ it "makes launcher executable" do
74
+ expect(launcher).to be_executable
75
+ end
76
+ end
77
+
78
+ it "deletes generic icon" do
79
+ expect(icon.parent.join('GenericApp.icns')).not_to exist
80
+ end
81
+
82
+ it "injects icon" do
83
+ expect(icon).to exist
84
+ end
85
+
86
+ it "injects jar" do
87
+ expect(jar).to exist
88
+ end
89
+
90
+ it "removes any extraneous jars" do
91
+ jar_dir_contents = @output_file.join("Contents/Java").children
92
+ expect(jar_dir_contents.reject {|f| f == jar }).to be_empty
93
+ end
94
+
95
+ describe "Info.plist" do
96
+ require 'plist'
97
+ before :all do
98
+ @plist = Plist.parse_xml(@output_file.join 'Contents/Info.plist')
99
+ end
100
+
101
+ it "sets identifier" do
102
+ expect(@plist['CFBundleIdentifier']).to eq('com.hackety.shoes.sweet-nebulae')
103
+ end
104
+
105
+ it "sets display name" do
106
+ expect(@plist['CFBundleDisplayName']).to eq('Sugar Clouds')
107
+ end
108
+
109
+ it "sets bundle name" do
110
+ expect(@plist['CFBundleName']).to eq('Sugar Clouds')
111
+ end
112
+
113
+ it "sets icon" do
114
+ expect(@plist['CFBundleIconFile']).to eq('boots.icns')
115
+ end
116
+
117
+ it "sets version" do
118
+ expect(@plist['CFBundleVersion']).to eq('0.0.1')
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "with an invalid configuration" do
124
+ let(:config) { Shoes::Package::Configuration.create }
125
+ subject { Shoes::Package::JarApp.new config }
126
+
127
+ it "fails to initialize" do
128
+ expect { subject }.to raise_error(Furoshiki::ConfigurationError)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,66 @@
1
+ require_relative 'spec_helper'
2
+ require 'shoes/package/configuration'
3
+ require 'shoes/package/jar'
4
+
5
+ include PackageHelpers
6
+
7
+ describe Furoshiki::Jar do
8
+ include_context 'config'
9
+ include_context 'package'
10
+
11
+ context "when creating a .jar" do
12
+ before :all do
13
+ @output_dir.rmtree if @output_dir.exist?
14
+ @output_dir.mkpath
15
+ config = Shoes::Package::Configuration.load(@config_filename)
16
+ @subject = Shoes::Package::Jar.new(config)
17
+ @jar_path = @subject.package
18
+ end
19
+
20
+ let(:jar_name) { 'sweet-nebulae.jar' }
21
+ let(:output_file) { Pathname.new(@output_dir.join jar_name) }
22
+ subject { @subject }
23
+
24
+ it "creates a .jar" do
25
+ expect(output_file).to exist
26
+ end
27
+
28
+ it "returns path to .jar" do
29
+ expect(@jar_path).to eq(output_file.to_s)
30
+ end
31
+
32
+ it "creates .jar smaller than 60MB" do
33
+ expect(File.size(output_file)).to be < 60 * 1024 * 1024
34
+ end
35
+
36
+ context "inspecting contents" do
37
+ let (:jar) { Zip::File.new(output_file) }
38
+
39
+ it "includes shoes-core" do
40
+ shoes_core = jar.glob "gems/shoes-core*"
41
+ expect(shoes_core.length).to equal(1)
42
+ end
43
+
44
+ it "includes shoes-swt" do
45
+ shoes_swt = jar.glob "gems/shoes-swt*"
46
+ expect(shoes_swt.length).to equal(1)
47
+ end
48
+
49
+ it "excludes directories recursively" do
50
+ expect(jar.entries).not_to include("dir_to_ignore/file_to_ignore")
51
+ end
52
+ end
53
+
54
+ its(:default_dir) { should eq(@output_dir) }
55
+ its(:filename) { should eq(jar_name) }
56
+ end
57
+
58
+ describe "with an invalid configuration" do
59
+ let(:config) { Shoes::Package::Configuration.create}
60
+ subject { Shoes::Package::Jar.new(config) }
61
+
62
+ it "fails to initialize" do
63
+ expect { subject }.to raise_error(Furoshiki::ConfigurationError)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,17 @@
1
+ name: Sugar Clouds
2
+ shortname: sweet-nebulae
3
+ ignore:
4
+ - pkg
5
+ - dir_to_ignore
6
+ run: bin/hello_world
7
+ gems: rspec
8
+ version: 0.0.1
9
+ release: Mindfully
10
+ icons:
11
+ osx: img/boots.icns
12
+ gtk: img/boots_512x512x32.png
13
+ win32: img/boots.ico
14
+ dmg:
15
+ ds_store: path/to/custom/.DS_Store
16
+ background: path/to/custom/background.png
17
+ custom: my custom feature
@@ -0,0 +1,3 @@
1
+ Shoes.app do
2
+ banner "Hello world"
3
+ end
@@ -0,0 +1 @@
1
+ should be ignored
Binary file
Binary file
@@ -0,0 +1 @@
1
+ # Just a sibling of 'app.yaml'
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shoes-package
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.0.0.pre3
5
+ platform: ruby
6
+ authors:
7
+ - Team Shoes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '='
17
+ - !ruby/object:Gem::Version
18
+ version: 4.0.0.pre3
19
+ name: shoes-core
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0.pre3
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.3.0
33
+ name: furoshiki
34
+ prerelease: false
35
+ type: :runtime
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.0
41
+ description: Application packaging for Shoes, the best little GUI toolkit for Ruby. Shoes makes building for Mac, Windows, and Linux super simple.
42
+ email:
43
+ - shoes@librelist.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - Rakefile
49
+ - lib/shoes/package/configuration.rb
50
+ - lib/shoes/package/jar.rb
51
+ - lib/shoes/package/jar_app.rb
52
+ - lib/shoes/package/version.rb
53
+ - lib/warbler/traits/shoes.rb
54
+ - shoes-package.gemspec
55
+ - spec/.furoshiki/cache/shoes-app-template.zip
56
+ - spec/configuration_spec.rb
57
+ - spec/spec_helper.rb
58
+ - spec/support/shared_config.rb
59
+ - spec/swt_app_spec.rb
60
+ - spec/swt_jar_spec.rb
61
+ - spec/test_app/app.yaml
62
+ - spec/test_app/bin/hello_world
63
+ - spec/test_app/dir_to_ignore/file_to_ignore.txt
64
+ - spec/test_app/img/boots.icns
65
+ - spec/test_app/img/boots.ico
66
+ - spec/test_app/img/boots_512x512x32.png
67
+ - spec/test_app/sibling.rb
68
+ homepage: https://github.com/shoes/shoes4
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>'
84
+ - !ruby/object:Gem::Version
85
+ version: 1.3.1
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.4.2
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Application packaging for Shoes, the best little GUI toolkit for Ruby.
92
+ test_files:
93
+ - spec/.furoshiki/cache/shoes-app-template.zip
94
+ - spec/configuration_spec.rb
95
+ - spec/spec_helper.rb
96
+ - spec/support/shared_config.rb
97
+ - spec/swt_app_spec.rb
98
+ - spec/swt_jar_spec.rb
99
+ - spec/test_app/app.yaml
100
+ - spec/test_app/bin/hello_world
101
+ - spec/test_app/dir_to_ignore/file_to_ignore.txt
102
+ - spec/test_app/img/boots.icns
103
+ - spec/test_app/img/boots.ico
104
+ - spec/test_app/img/boots_512x512x32.png
105
+ - spec/test_app/sibling.rb
106
+ has_rdoc: