wrapp 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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