wrapp 0.1.2 → 0.2.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.
data/README.md CHANGED
@@ -6,11 +6,11 @@ Wrap an App... in a disk image (DMG).
6
6
  ## Prologue
7
7
 
8
8
  Say you wanna put your nice Mac OS X application in a handy disk image
9
- (DMG) for download / deployment.
10
- Why not use `wrapp` for this?
9
+ (DMG) for distribution.
10
+ Why not use *wrapp* for this?
11
11
  It is even shorter to type then `hdiutil` ;-)
12
12
 
13
- **NOTE: This only runs on Mac OS X!**
13
+ **NOTE: This runs on Mac OS X only!**
14
14
 
15
15
 
16
16
  ## Installation
@@ -30,32 +30,26 @@ Or install it yourself as:
30
30
 
31
31
  ## Usage
32
32
 
33
+ Try `wrapp --help`!
34
+
33
35
  Some examples...
34
36
 
35
- Build a dmg from the locally installed 'Chunky Bacon.app':
37
+ Wrap the *Chunky Bacon* App:
36
38
 
37
39
  ```
38
40
  wrapp /Applications/Chunky\ Bacon.app
39
- created chunky_bacon_1.2.3.dmg with SHA-1 deadbeef...
40
41
  ```
41
42
 
42
- **NOTE: Not yet implemented!**
43
- Build a dmg from the Chunky Bacon app (the one with the weird directory
44
- layout):
43
+ Wrap the *Chunky Bacon* App and include the parent directory (some stuff
44
+ like *TeamViewer* or *FileMaker* reside in sub-directories of
45
+ `/Applications` rather then the top-level):
45
46
 
46
47
  ```
47
- wrapp --plist /Applications/Chunky/Bacon.app /Applications/Chunky
48
- created bacon_1.2.3.dmg with SHA-1 deadbeef...
48
+ wrapp --include-parent-dir /Applications/why/Chunky Bacon.app
49
49
  ```
50
50
 
51
- **NOTE: Not yet implemented!**
52
- Build the dmg in a different directory (and create it first if missing):
53
-
54
- ```
55
- wrapp --outdir /tmp/dmgs /Applications/Chunky\ Bacon.app
56
- ...
57
- created chunky_bacon_1.2.3.dmg with SHA-1 deadbeef...
58
- ```
51
+ The commands create a DMG like `chunky_bacon_1.2.3.dmg` (named after the
52
+ App + Version) that contains the given App.
59
53
 
60
54
  Thats it.
61
55
 
data/bin/wrapp CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'wrapp'
4
4
 
5
- Wrapp::DMGBuilder.run
5
+ Wrapp::CLI.run
@@ -1,58 +1,72 @@
1
- def create_app
2
- FileUtils.rm_f(dmg_filename)
3
- write_file(plist_path, plist_content)
1
+ # Helpers
2
+
3
+ def create_app(*opts)
4
+ app = App.new(*opts)
5
+ FileUtils.rm_f(app.dmg_filename)
6
+ write_file(app.plist_path, app.plist_content)
7
+ app
4
8
  end
5
9
 
6
- def plist_path
7
- File.join(app_path, 'Contents', 'Info.plist')
10
+
11
+ def attach_dmg
12
+ assert_dmg_exists
13
+ create_dir(volumes_dir)
14
+ cmd = "hdiutil attach '#{@app.dmg_filename}' -nobrowse -mountroot '#{volumes_dir}'"
15
+ run_simple(cmd, true)
8
16
  end
9
17
 
10
- def plist_content
11
- %Q{<?xml version="1.0" encoding="UTF-8"?>
12
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
13
- <plist version="1.0">
14
- <dict>
15
- <key>CFBundleName</key>
16
- <string>#{app_name}</string>
17
- <key>CFBundleShortVersionString</key>
18
- <string>#{app_version}</string>
19
- </dict>
20
- </plist>
21
- }
18
+ def detach_dmg
19
+ in_current_dir do
20
+ Dir.glob("#{volumes_dir}/*") do |dir|
21
+ system("hdiutil detach '#{dir}' -force >/dev/null")
22
+ end
23
+ end
22
24
  end
23
25
 
24
- def run_wrapp_command
25
- cmd = "wrapp '#{app_path}'"
26
- run_simple(unescape(cmd))
26
+ def assert_dmg_exists
27
+ check_file_presence([@app.dmg_filename], true)
27
28
  end
28
29
 
29
- def dmg_filename
30
- 'chunky_bacon_1.2.3.dmg'
30
+ def volumes_dir
31
+ 'Volumes' # We don't want to attach to '/Volumes' in our tests.
31
32
  end
32
33
 
33
- def app_version
34
- '1.2.3'
34
+
35
+ # Hooks
36
+
37
+ After do
38
+ detach_dmg
35
39
  end
36
40
 
37
- def app_name
38
- 'Chunky Bacon'
41
+
42
+ # Step definitions
43
+
44
+ Given(/^an App$/) do
45
+ @app = create_app
39
46
  end
40
47
 
41
- def app_path
42
- "Applications/#{app_name}.app"
48
+ Given(/^an App in a directory$/) do
49
+ @app = create_app(:prefix => 'Stuff')
43
50
  end
44
51
 
45
- Given(/^an App$/) do
46
- create_app
52
+ When(/^I wrap the App$/) do
53
+ cmd = "wrapp '#{@app.app_path}'"
54
+ run_simple(unescape(cmd))
55
+ end
56
+
57
+ When(/^I wrap the App including the parent directory$/) do
58
+ cmd = "wrapp --include-parent-dir '#{@app.app_path}'"
59
+ run_simple(unescape(cmd))
47
60
  end
48
61
 
49
- When(/^I run wrapp$/) do
50
- run_wrapp_command
62
+ Then(/^the App should be wrapped$/) do
63
+ attach_dmg
64
+ attached_app_path = File.join(volumes_dir, @app.app_name)
65
+ check_directory_presence([attached_app_path], true)
51
66
  end
52
67
 
53
- Then(/^the App should be wrapped in a DMG$/) do
54
- check_file_presence([dmg_filename], true) # assert that dmg exists
55
- # attach dmg
56
- # assert that dmg contains the app dir (basedir w/o full path)
57
- # detach dmg
68
+ Then(/^the App should be wrapped including the parent directory$/) do
69
+ attach_dmg
70
+ attached_app_path = File.join(volumes_dir, @app.prefix)
71
+ check_directory_presence([attached_app_path], true)
58
72
  end
@@ -0,0 +1,44 @@
1
+ class App
2
+ def initialize(opts = {})
3
+ @opts = opts
4
+ end
5
+
6
+ def plist_path
7
+ File.join(app_path, 'Contents', 'Info.plist')
8
+ end
9
+
10
+ def plist_content
11
+ %Q{<?xml version="1.0" encoding="UTF-8"?>
12
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
13
+ <plist version="1.0">
14
+ <dict>
15
+ <key>CFBundleName</key>
16
+ <string>#{app_name}</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>#{app_version}</string>
19
+ </dict>
20
+ </plist>
21
+ }
22
+ end
23
+
24
+ def dmg_filename
25
+ 'chunky_bacon_1.2.3.dmg'
26
+ end
27
+
28
+ def app_version
29
+ '1.2.3'
30
+ end
31
+
32
+ def app_name
33
+ 'Chunky Bacon'
34
+ end
35
+
36
+ def prefix
37
+ @opts[:prefix]
38
+ end
39
+
40
+ def app_path
41
+ basedir = "#{app_name}.app"
42
+ (prefix && File.join(prefix, basedir)) || basedir
43
+ end
44
+ end
@@ -4,10 +4,12 @@ Feature: Wrap App
4
4
  As as user
5
5
  I want wrap my App in a DMG
6
6
 
7
- Scenario: Create DMG
7
+ Scenario: Wrap App
8
8
  Given an App
9
- When I run wrapp
10
- Then the App should be wrapped in a DMG
9
+ When I wrap the App
10
+ Then the App should be wrapped
11
11
 
12
- #Scenario: Create DMG with different output directory
13
- #Scenario: Create DMG with differnt info plist
12
+ Scenario: Wrap App including the parent directory
13
+ Given an App in a directory
14
+ When I wrap the App including the parent directory
15
+ Then the App should be wrapped including the parent directory
data/lib/wrapp/cli.rb ADDED
@@ -0,0 +1,23 @@
1
+ module Wrapp
2
+ class CLI
3
+ include Mixlib::CLI
4
+
5
+ option :include_parent_dir,
6
+ :long => '--include-parent-dir'
7
+
8
+ class << self
9
+ def run
10
+ new.run(ARGV)
11
+ end
12
+ end
13
+
14
+ def run(argv)
15
+ app_path = parse_options(argv).first
16
+ wrapp(app_path, config)
17
+ end
18
+
19
+ def wrapp(*opts)
20
+ DMGBuilder.new(*opts).create
21
+ end
22
+ end
23
+ end
@@ -2,28 +2,19 @@ module Wrapp
2
2
  class DMGBuilder
3
3
  attr_reader :app_path
4
4
 
5
- class << self
6
- def run
7
- new(ARGV.first).create #TODO: Test this!
8
- end
9
- end
10
-
11
- def initialize(app_path)
5
+ def initialize(app_path, opts = {})
12
6
  @app_path = app_path
7
+ @opts = opts
13
8
  end
14
9
 
15
10
  def create
16
- create_dmg
11
+ system("hdiutil create '#{dmg_filename}' -srcfolder '#{source_path}'")
17
12
  end
18
13
 
19
14
  private
20
15
 
21
- def create_dmg
22
- system("hdiutil create '#{dmg_path}' -srcfolder '#{app_path}'")
23
- end
24
-
25
- def dmg_path
26
- dmg_filename
16
+ def source_path
17
+ @opts[:include_parent_dir] ? File.dirname(app_path) : app_path
27
18
  end
28
19
 
29
20
  def dmg_filename
data/lib/wrapp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Wrapp
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/wrapp.rb CHANGED
@@ -1,4 +1,6 @@
1
+ require 'mixlib/cli'
1
2
  require 'plist'
2
3
  require 'wrapp/version'
3
4
  require 'wrapp/app_info'
4
5
  require 'wrapp/dmg_builder'
6
+ require 'wrapp/cli'
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module Wrapp
4
+ describe CLI do
5
+ let(:cli) { CLI.new }
6
+ let(:app_path) { '/Applications/Chunky Bacon.app' }
7
+
8
+ describe '.run' do
9
+ it 'runs an instance with ARGV' do
10
+ cli.should_receive(:run).with(ARGV)
11
+ CLI.stub(:new).and_return(cli)
12
+ CLI.run
13
+ end
14
+ end
15
+
16
+ describe '#run' do
17
+ let(:argv) { [app_path] }
18
+
19
+ it 'wraps the app' do
20
+ cli.should_receive(:wrapp).with(app_path, {})
21
+ cli.run(argv)
22
+ end
23
+
24
+ %w(--include-parent-dir -i).each do |opt|
25
+ context "with #{opt}" do
26
+ let(:argv) { [app_path, opt] }
27
+
28
+ it 'wraps the app including the parent directory' do
29
+ cli.should_receive(:wrapp).
30
+ with(app_path, :include_parent_dir => true)
31
+ cli.run(argv)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ describe '#wrapp' do
38
+ it 'creates the dmg via dmg builder' do
39
+ opts = %(some options and arguments)
40
+ dmg = double('dmg_builder')
41
+ dmg.should_receive(:create)
42
+ DMGBuilder.should_receive(:new).with(*opts).and_return(dmg)
43
+ cli.wrapp(*opts)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -9,41 +9,37 @@ module Wrapp
9
9
  DMGBuilder.any_instance.stub(:system)
10
10
  end
11
11
 
12
- describe '.run' do
13
- it 'creates the dmg' do
14
- DMGBuilder.stub(:new).and_return(dmg)
15
- dmg.should_receive(:create) #TODO: Fix nil warning!
16
- DMGBuilder.run
17
- end
18
- end
19
-
20
12
  describe '#create' do
21
- it 'creates the dmg and directory' do
22
- dmg.should_receive(:create_dmg)
23
- dmg.create
24
- end
25
- end
26
-
27
- describe '#create_dmg' do
28
13
  it 'creates the dmg by hdiutil' do
29
- dmg.should_receive(:app_path).and_return('Chunky.app')
30
- dmg.should_receive(:dmg_path).and_return('bacon.dmg')
14
+ dmg.should_receive(:source_path).and_return('Chunky.app')
15
+ dmg.should_receive(:dmg_filename).and_return('bacon.dmg')
31
16
  dmg.should_receive(:system).
32
17
  with("hdiutil create 'bacon.dmg' -srcfolder 'Chunky.app'")
33
- dmg.send(:create_dmg)
18
+ dmg.create
34
19
  end
35
20
  end
36
21
 
37
22
  describe '#app_path' do
38
- it 'returns the path to the app' do
23
+ it 'returns the app path' do
39
24
  expect(dmg.app_path).to eq('Chunky Bacon.app')
40
25
  end
41
26
  end
42
27
 
43
- describe '#dmg_path' do
44
- it 'returns the dmg_filename' do
45
- dmg.should_receive(:dmg_filename).and_return('chunky_bacon.dmg')
46
- expect(dmg.send(:dmg_path)).to eq('chunky_bacon.dmg')
28
+ describe '#source_path' do
29
+ before do
30
+ dmg.should_receive(:app_path).and_return('Chunky/Bacon.app')
31
+ end
32
+
33
+ it 'returns the path of the app dir' do
34
+ expect(dmg.send(:source_path)).to eq('Chunky/Bacon.app')
35
+ end
36
+
37
+ context 'with :include_parent_dir => true' do
38
+ let(:dmg) { DMGBuilder.new('...', :include_parent_dir => true) }
39
+
40
+ it 'returns the path of the app parent dir' do
41
+ expect(dmg.send(:source_path)).to eq('Chunky')
42
+ end
47
43
  end
48
44
  end
49
45
 
data/wrapp.gemspec CHANGED
@@ -19,10 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'plist', '~> 3.1'
22
+ spec.add_dependency 'mixlib-cli', '~> 1.3'
22
23
 
23
24
  spec.add_development_dependency 'bundler', '~> 1.3'
24
25
  spec.add_development_dependency 'rake'
25
- spec.add_development_dependency 'guard', '~> 1.8'
26
+ spec.add_development_dependency 'guard'
26
27
  spec.add_development_dependency 'guard-cucumber'
27
28
  spec.add_development_dependency 'guard-rspec'
28
29
  spec.add_development_dependency 'aruba'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wrapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-16 00:00:00.000000000 Z
12
+ date: 2013-10-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: plist
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '3.1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mixlib-cli
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.3'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.3'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: bundler
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -64,17 +80,17 @@ dependencies:
64
80
  requirement: !ruby/object:Gem::Requirement
65
81
  none: false
66
82
  requirements:
67
- - - ~>
83
+ - - ! '>='
68
84
  - !ruby/object:Gem::Version
69
- version: '1.8'
85
+ version: '0'
70
86
  type: :development
71
87
  prerelease: false
72
88
  version_requirements: !ruby/object:Gem::Requirement
73
89
  none: false
74
90
  requirements:
75
- - - ~>
91
+ - - ! '>='
76
92
  - !ruby/object:Gem::Version
77
- version: '1.8'
93
+ version: '0'
78
94
  - !ruby/object:Gem::Dependency
79
95
  name: guard-cucumber
80
96
  requirement: !ruby/object:Gem::Requirement
@@ -139,14 +155,17 @@ files:
139
155
  - Rakefile
140
156
  - bin/wrapp
141
157
  - features/step_definitions/wrapp_steps.rb
158
+ - features/support/app.rb
142
159
  - features/support/env.rb
143
160
  - features/wrap_app.feature
144
161
  - lib/wrapp.rb
145
162
  - lib/wrapp/app_info.rb
163
+ - lib/wrapp/cli.rb
146
164
  - lib/wrapp/dmg_builder.rb
147
165
  - lib/wrapp/version.rb
148
166
  - spec/spec_helper.rb
149
167
  - spec/wrapp/app_info_spec.rb
168
+ - spec/wrapp/cli_spec.rb
150
169
  - spec/wrapp/dmg_builder_spec.rb
151
170
  - wrapp.gemspec
152
171
  homepage: https://github.com/bjoernalbers/wrapp
@@ -164,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
183
  version: '0'
165
184
  segments:
166
185
  - 0
167
- hash: -1767770201264435998
186
+ hash: 983932024076404850
168
187
  required_rubygems_version: !ruby/object:Gem::Requirement
169
188
  none: false
170
189
  requirements:
@@ -173,17 +192,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
192
  version: '0'
174
193
  segments:
175
194
  - 0
176
- hash: -1767770201264435998
195
+ hash: 983932024076404850
177
196
  requirements: []
178
197
  rubyforge_project:
179
198
  rubygems_version: 1.8.23
180
199
  signing_key:
181
200
  specification_version: 3
182
- summary: wrapp-0.1.2
201
+ summary: wrapp-0.2.0
183
202
  test_files:
184
203
  - features/step_definitions/wrapp_steps.rb
204
+ - features/support/app.rb
185
205
  - features/support/env.rb
186
206
  - features/wrap_app.feature
187
207
  - spec/spec_helper.rb
188
208
  - spec/wrapp/app_info_spec.rb
209
+ - spec/wrapp/cli_spec.rb
189
210
  - spec/wrapp/dmg_builder_spec.rb