chocbomb 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/LICENSE.txt ADDED
@@ -0,0 +1,34 @@
1
+ Copyright (c) 2011 glejeune
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ ---
23
+
24
+ A HUGE PART OF THE CODE COME FROM THE CHOCTOP PROJECT AND IS LICENCED UNDER THE MIT LICENCE :
25
+
26
+ (The MIT License)
27
+
28
+ Copyright © 2009 Dr Nic Williams, drnicwilliams@gmail.com
29
+
30
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
31
+
32
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
33
+
34
+ THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,34 @@
1
+ = ChocBomb
2
+
3
+ ChocBomb is a shameful copy of ChocTop[https://github.com/drnic/choctop] - Build and deploy tools for Cocoa apps using Sparkle for distributions and upgrades; it’s like Hoe but for Cocoa apps.
4
+
5
+ == So, Why not ChocTop ?
6
+
7
+ ChocTop[https://github.com/drnic/choctop] depends on RubyCocoa. Andif it is installed on every Mac 10.5+, it can only be used with the default's ruby installation. ChocBomb can be use (but this was not tested yet ;)) with ruby 1.8/1.9, macruby, jRuby, ...
8
+
9
+ This choise don't comes without any consequences... And ChocBomb is (right now) very incomplete, compare to ChocTop!
10
+
11
+ == Contributing to ChocBomb
12
+
13
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
14
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
15
+ * Fork the project
16
+ * Start a feature/bugfix branch
17
+ * Commit and push until you are happy with your contribution
18
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
19
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
20
+
21
+ == Copyright
22
+
23
+ A huge part of the code come from the ChocTop[https://github.com/drnic/choctop] project and is Copyright © 2009-2011 Dr Nic Williams, drnicwilliams@gmail.com under the MIT Licence.
24
+
25
+ (The MIT License)
26
+
27
+ Copyright © 2011 Gregoire Lejeune, gregoire.lejeune@free.fr
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
30
+
31
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
32
+
33
+ THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
+
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gem|
6
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
7
+ gem.name = "chocbomb"
8
+ gem.homepage = "http://github.com/glejeune/chocbomb"
9
+ gem.license = "MIT"
10
+ gem.summary = %Q{ChocBomb is a shameful copy of ChocTop}
11
+ gem.description = %Q{ChocBomb is a shameful copy of ChocTop - Build and deploy tools for Cocoa apps using Sparkle for distributions and upgrades; it’s like Hoe but for Cocoa apps.}
12
+ gem.email = "gregoire.lejeune@gmail.com"
13
+ gem.authors = ["glejeune"]
14
+ gem.add_dependency "plist", ">= 3.1.0"
15
+ gem.add_dependency "escape", ">= 0.0.4"
16
+ gem.add_dependency "builder",">=2.1.2"
17
+ gem.add_dependency "RedCloth", ">=4.2.3"
18
+
19
+ gem.add_development_dependency "jeweler", "~> 1.5.2"
20
+ gem.add_development_dependency "rcov", ">= 0"
21
+ end
22
+ Jeweler::RubygemsDotOrgTasks.new
23
+
24
+ require 'rake/testtask'
25
+ Rake::TestTask.new(:test) do |test|
26
+ test.libs << 'lib' << 'test'
27
+ test.pattern = 'test/**/test_*.rb'
28
+ test.verbose = true
29
+ end
30
+
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+
38
+ task :default => :test
39
+
40
+ require 'rake/rdoctask'
41
+ Rake::RDocTask.new do |rdoc|
42
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "chocbomb #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/bin/chocbomb ADDED
@@ -0,0 +1,7 @@
1
+ #!ruby
2
+
3
+ require 'erb'
4
+
5
+ templates = File.expand_path(File.join(File.dirname($0), "..", "templates"))
6
+ data = ERB.new(open(File.join(templates, "Rakefile.erb")).read).result(binding)
7
+ File.open("Rakefile", 'w') {|f| f.write(data) }
@@ -0,0 +1,39 @@
1
+ require 'chocbomb/tools/dmg'
2
+ require 'chocbomb/tools/xcode'
3
+ require 'chocbomb/tools/feed'
4
+
5
+ module ChocBomb
6
+ module Tasks
7
+ include Tools
8
+
9
+ def define_tasks
10
+ return unless Object.const_defined?("Rake")
11
+
12
+ desc "Build #{@name} #{@build_type}"
13
+ task :build => "build/#{@build_type}/#{@name}/Contents/Info.plist"
14
+
15
+ task "build/#{@build_type}/#{@name}/Contents/Info.plist" do
16
+ XCode.build(self)
17
+ end
18
+
19
+ desc "Create the dmg file"
20
+ task :dmg do
21
+ DMG.detach(self)
22
+ DMG.make(self)
23
+ DMG.detach(self)
24
+ DMG.readonly(self)
25
+ end
26
+
27
+ desc "Create feed"
28
+ task :feed do
29
+ Feed.make_appcast(self)
30
+ Feed.make_dmg_symlink(self)
31
+ Feed.make_index_redirect(self)
32
+ Feed.make_release_notes(self)
33
+ end
34
+
35
+ desc "All"
36
+ task :appcast => [:build, :dmg, :feed]
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,209 @@
1
+ require 'chocbomb/tools/images'
2
+
3
+ module ChocBomb
4
+ module Tools
5
+ class DMG
6
+ attr_accessor :chocbomb
7
+ def initialize(cb)
8
+ @chocbomb = cb
9
+ @files = {}
10
+ end
11
+
12
+ def self.detach(cb)
13
+ self.new(cb).detach
14
+ end
15
+
16
+ def self.make(cb)
17
+ self.new(cb).make
18
+ end
19
+
20
+
21
+ def self.readonly(cb)
22
+ self.new(cb).readonly
23
+ end
24
+
25
+ def detach
26
+ mounted_paths = `hdiutil info | grep '#{chocbomb.volume_path}' | grep "Apple_HFS"`.split("\n").map { |e| e.split(" ").first }
27
+ mounted_paths.each do |path|
28
+ begin
29
+ sh "hdiutil detach '#{path}' -quiet -force"
30
+ rescue StandardError => e
31
+ p e
32
+ end
33
+ end
34
+ end
35
+
36
+ def make
37
+ @files = chocbomb.files.inject({}) do |files, file|
38
+ path_or_helper, options = file
39
+ path = case path_or_helper
40
+ when Symbol
41
+ chocbomb.send path_or_helper
42
+ when Proc
43
+ path_or_helper.call
44
+ else
45
+ path_or_helper
46
+ end
47
+ if path && File.exists?(path)
48
+ files[path] = options
49
+ options[:name] ||= File.basename(path)
50
+ end
51
+ files
52
+ end
53
+
54
+ FileUtils.rm_r(chocbomb.dmg_src_folder) if File.exists? chocbomb.dmg_src_folder
55
+ FileUtils.mkdir_p(chocbomb.dmg_src_folder)
56
+
57
+ @files.each do |path, options|
58
+ if options[:link]
59
+ webloc = <<-WEBLOC.gsub(/^ /, '')
60
+ <?xml version="1.0" encoding="UTF-8"?>
61
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
62
+ <plist version="1.0">
63
+ <dict>
64
+ <key>URL</key>
65
+ <string>#{options[:url]}</string>
66
+ </dict>
67
+ </plist>
68
+ WEBLOC
69
+
70
+ target = File.join(dmg_src_folder, options[:name])
71
+ File.new(target).print webloc
72
+ else
73
+ target = File.join(chocbomb.dmg_src_folder, options[:name])
74
+ FileUtils.copy_entry(path, target)
75
+ if options[:exclude]
76
+ exclude_list = options[:exclude].is_a?(Array) ? options[:exclude] : [options[:exclude].to_s]
77
+ exclude_list.each { |exclude| sh ::Escape.shell_command(['rm', '-rf', File.join(target, exclude)]) }
78
+ end
79
+ end
80
+ end
81
+
82
+ FileUtils.mkdir_p chocbomb.build_path
83
+ FileUtils.rm_f(chocbomb.pkg)
84
+ sh "hdiutil create -format UDRW -quiet -volname '#{chocbomb.name}' -srcfolder '#{chocbomb.dmg_src_folder}' '#{chocbomb.pkg}'"
85
+ mount
86
+ sh "bless --folder '#{chocbomb.volume_path}' --openfolder '#{chocbomb.volume_path}'"
87
+ sh "sleep 1"
88
+
89
+ # Add Volume Icon
90
+ FileUtils.cp(chocbomb.volume_icon, "#{chocbomb.volume_path}/.VolumeIcon.icns")
91
+ sh "SetFile -a C '#{chocbomb.volume_path}'"
92
+
93
+ # Configure Application Icon
94
+ Mac.applescript <<-SCRIPT.gsub(/^ /, ''), "apps_icon_script"
95
+ tell application "Finder"
96
+ set applications_folder to displayed name of (path to applications folder) -- i18n
97
+ set dest to disk "#{chocbomb.name}"
98
+ set src to folder applications_folder of startup disk
99
+ make new alias at dest to src
100
+ end tell
101
+ SCRIPT
102
+
103
+ # Configure DMG Window
104
+ if chocbomb.background_file
105
+ target_background = "#{chocbomb.volume_path}/#{chocbomb.volume_background}"
106
+ FileUtils.mkdir_p(File.dirname(target_background))
107
+ FileUtils.cp(chocbomb.background_file, target_background)
108
+ end
109
+ Mac.applescript <<-SCRIPT.gsub(/^ /, '')
110
+ tell application "Finder"
111
+ set applications_folder to displayed name of (path to applications folder) -- i18n
112
+ set mountpoint to POSIX file ("#{chocbomb.volume_path}" as string) as alias
113
+ tell folder mountpoint
114
+ open
115
+ tell container window
116
+ set toolbar visible to false
117
+ set statusbar visible to false -- doesn't do anything at DMG open time
118
+ set current view to icon view
119
+ delay 1 -- Sync
120
+ set the bounds to {#{window_bounds.join(", ")}}
121
+ end tell
122
+ delay 1 -- Sync
123
+ set icon size of the icon view options of container window to #{chocbomb.icon_size}
124
+ set text size of the icon view options of container window to #{chocbomb.icon_text_size}
125
+ set arrangement of the icon view options of container window to not arranged
126
+ #{set_position_of_files}
127
+ #{set_position_of_shortcuts}
128
+ close
129
+ open
130
+ set the bounds of the container window to {#{window_bounds.join(", ")}}
131
+ set background picture of the icon view options of container window to file "#{chocbomb.volume_background.gsub(/\//,':')}"
132
+ update without registering applications
133
+ delay 5 -- Sync
134
+ close
135
+ end tell
136
+ -- Sync
137
+ delay 5
138
+ end tell
139
+ SCRIPT
140
+ sh "SetFile -a V '#{target_background}'" if chocbomb.background_file
141
+ end
142
+
143
+ def readonly
144
+ tmp_path = "/tmp/#{chocbomb.name}-rw.dmg"
145
+ FileUtils.mv(chocbomb.pkg, tmp_path)
146
+ sh "hdiutil convert '#{tmp_path}' -format UDZO -imagekey zlib-level=9 -o '#{chocbomb.pkg}'"
147
+ end
148
+
149
+ private
150
+ def mount
151
+ sh "hdiutil attach '#{chocbomb.pkg}' -mountpoint '#{chocbomb.volume_path}' -noautoopen -quiet"
152
+ end
153
+
154
+ def window_position
155
+ [50, 100]
156
+ end
157
+
158
+ def window_bounds
159
+ window_position +
160
+ window_position.zip(background_bounds).map { |w, b| w + b }
161
+ end
162
+
163
+ def background_bounds
164
+ return [400, 300] unless chocbomb.background_file
165
+ return ChocBomb::Tools::Images.size(chocbomb.background_file)
166
+ end
167
+
168
+ def set_position_of_files
169
+ @files.map do |file_options|
170
+ path, options = file_options
171
+ target = options[:name]
172
+ position = options[:position].join(", ")
173
+ %Q{set position of item "#{target}" to {#{position}}}
174
+ end.join("\n")
175
+ end
176
+
177
+ def set_position_of_shortcuts
178
+ if include_applications_icon?
179
+ %Q{set position of item applications_folder to {#{chocbomb.applications_icon_position.join(", ")}}}
180
+ else
181
+ ""
182
+ end
183
+ end
184
+
185
+ def include_applications_icon?
186
+ # target =~ /.app$/
187
+ true
188
+ end
189
+ end
190
+
191
+ module AppCast
192
+ end
193
+
194
+ module Mac
195
+ def self.applescript(applescript, tmp_file = "chocbomb-script")
196
+ File.open(scriptfile = "/tmp/#{tmp_file}", "w") do |f|
197
+ f << applescript
198
+ end
199
+ sh("osascript #{scriptfile}") do |ok, res|
200
+ if ! ok
201
+ p res
202
+ exit 1
203
+ end
204
+ end
205
+ applescript
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,104 @@
1
+ require 'builder'
2
+ require 'RedCloth'
3
+
4
+ module ChocBomb
5
+ module Tools
6
+ class Feed
7
+ attr_accessor :chocbomb
8
+ def initialize(cb)
9
+ @chocbomb = cb
10
+ end
11
+
12
+ def self.make_appcast(cb)
13
+ self.new(cb).make_appcast
14
+ end
15
+
16
+ def self.make_dmg_symlink(cb)
17
+ self.new(cb).make_dmg_symlink
18
+ end
19
+
20
+ def self.make_index_redirect(cb)
21
+ self.new(cb).make_index_redirect
22
+ end
23
+
24
+ def self.make_release_notes(cb)
25
+ self.new(cb).make_release_notes
26
+ end
27
+
28
+ def make_appcast
29
+ FileUtils.mkdir_p(chocbomb.build_path)
30
+ appcast = File.open("#{chocbomb.build_path}/#{chocbomb.appcast_filename}", 'w') do |f|
31
+ xml = Builder::XmlMarkup.new(:indent => 2)
32
+ xml.instruct!
33
+ xml_string = xml.rss('xmlns:atom' => "http://www.w3.org/2005/Atom",
34
+ 'xmlns:sparkle' => "http://www.andymatuschak.org/xml-namespaces/sparkle",
35
+ :version => "2.0") do
36
+ xml.channel do
37
+ xml.title(@name)
38
+ xml.description("#{chocbomb.name} updates")
39
+ xml.link(chocbomb.base_url)
40
+ xml.language('en')
41
+ xml.pubDate( Time.now.strftime("%a, %d %b %Y %H:%M:%S %z") )
42
+ # xml.lastBuildDate(Time.now.rfc822)
43
+ xml.atom(:link, :href => "#{chocbomb.base_url}/#{chocbomb.appcast_filename}",
44
+ :rel => "self", :type => "application/rss+xml")
45
+
46
+ xml.item do
47
+ xml.title("#{chocbomb.name} #{chocbomb.version}")
48
+ xml.tag! "sparkle:releaseNotesLink", "#{chocbomb.base_url}/#{chocbomb.release_notes}"
49
+ xml.pubDate Time.now.strftime("%a, %d %b %Y %H:%M:%S %z")
50
+ xml.guid("#{chocbomb.name}-#{chocbomb.version}", :isPermaLink => "false")
51
+ xml.enclosure(:url => "#{chocbomb.base_url}/#{chocbomb.pkg_name}",
52
+ :length => "#{File.size(chocbomb.pkg)}",
53
+ :type => "application/dmg",
54
+ :"sparkle:version" => chocbomb.version,
55
+ :"sparkle:dsaSignature" => chocbomb.dsa_signature)
56
+ end
57
+ end
58
+ end
59
+ f << xml_string
60
+ end
61
+ end
62
+
63
+ def make_dmg_symlink
64
+ if chocbomb.pkg_name != chocbomb.versionless_pkg_name
65
+ FileUtils.chdir(chocbomb.build_path) do
66
+ `rm '#{chocbomb.versionless_pkg_name}'`
67
+ `ln -s '#{chocbomb.pkg_name}' '#{chocbomb.versionless_pkg_name}'`
68
+ end
69
+ end
70
+ end
71
+
72
+ def make_index_redirect
73
+ File.open("#{chocbomb.build_path}/index.php", 'w') do |f|
74
+ f << %Q{<?php header("Location: #{chocbomb.pkg_relative_url}"); ?>}
75
+ end
76
+ end
77
+
78
+ def make_release_notes
79
+ if File.exist?(chocbomb.release_notes_template)
80
+ File.open("#{chocbomb.build_path}/#{chocbomb.release_notes}", "w") do |f|
81
+ template = File.read(chocbomb.release_notes_template)
82
+ f << ERB.new(template).result(binding)
83
+ end
84
+ end
85
+ end
86
+
87
+ def release_notes_content
88
+ if File.exists?("release_notes.txt")
89
+ File.read("release_notes.txt")
90
+ else
91
+ <<-TEXTILE.gsub(/^ /, '')
92
+ h1. #{version} #{Date.today}
93
+
94
+ h2. Another awesome release!
95
+ TEXTILE
96
+ end
97
+ end
98
+
99
+ def release_notes_html
100
+ RedCloth.new(release_notes_content).to_html
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,62 @@
1
+ module ChocBomb
2
+ module Tools
3
+ module Images
4
+ def self.size(file)
5
+ if File.extname(file) == ".png"
6
+ png(file)
7
+ else
8
+ jpeg(file)
9
+ end
10
+ end
11
+
12
+ def self.png(file)
13
+ IO.read(file)[0x10..0x18].unpack('NN')
14
+ end
15
+
16
+ def self.jpeg(file)
17
+ j = JPEG.new(file)
18
+ [j.width, j.height]
19
+ end
20
+
21
+ class JPEG
22
+ attr_reader :width, :height, :bits
23
+
24
+ def initialize(file)
25
+ if file.kind_of? IO
26
+ examine(file)
27
+ else
28
+ File.open(file, 'rb') { |io| examine(io) }
29
+ end
30
+ end
31
+
32
+ private
33
+ def examine(io)
34
+ raise 'malformed JPEG' unless io.getc == 0xFF && io.getc == 0xD8 # SOI
35
+
36
+ class << io
37
+ def readint; (readchar << 8) + readchar; end
38
+ def readframe; read(readint - 2); end
39
+ def readsof; [readint, readchar, readint, readint, readchar]; end
40
+ def next
41
+ c = readchar while c != 0xFF
42
+ c = readchar while c == 0xFF
43
+ c
44
+ end
45
+ end
46
+
47
+ while marker = io.next
48
+ case marker
49
+ when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
50
+ length, @bits, @height, @width, components = io.readsof
51
+ raise 'malformed JPEG' unless length == 8 + components * 3
52
+ when 0xD9, 0xDA: break # EOI, SOS
53
+ when 0xFE: @comment = io.readframe # COM
54
+ when 0xE1: io.readframe # APP1, contains EXIF tag
55
+ else io.readframe # ignore frame
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,9 @@
1
+ module ChocBomb
2
+ module Tools
3
+ module XCode
4
+ def self.build(cb)
5
+ sh "xcodebuild -configuration #{cb.build_type} -target #{cb.target} #{cb.build_options}"
6
+ end
7
+ end
8
+ end
9
+ end
data/lib/chocbomb.rb ADDED
@@ -0,0 +1,151 @@
1
+ require 'uri'
2
+ require 'rubygems'
3
+ require 'plist'
4
+ require 'escape'
5
+ require 'chocbomb/rake/tasks'
6
+
7
+ module ChocBomb
8
+ class Configuration
9
+ include Tasks
10
+
11
+ attr_accessor :host
12
+ attr_accessor :base_url
13
+ attr_accessor :su_feed_url
14
+
15
+ attr_accessor :release_notes
16
+ attr_accessor :private_key
17
+
18
+ # The background image
19
+ attr_accessor :background_file
20
+
21
+ # Position of the icon app
22
+ attr_accessor :app_icon_position
23
+
24
+ # Position of the Application symlink icon
25
+ attr_accessor :applications_icon_position
26
+
27
+ # Icns for the volume icon
28
+ attr_accessor :volume_icon
29
+
30
+ # Build type (Release, Debug, ...)
31
+ attr_accessor :build_type
32
+
33
+ # Target
34
+ attr_accessor :target
35
+
36
+ # Build options
37
+ attr_accessor :build_options
38
+
39
+ attr_accessor :icon_size
40
+ attr_accessor :icon_text_size
41
+
42
+ # Add an explicit file/bundle/folder into the DMG
43
+ # Examples:
44
+ # file 'build/Release/SampleApp.app', :position => [50, 100]
45
+ # file :target_bundle, :position => [50, 100]
46
+ # file proc { 'README.txt' }, :position => [50, 100]
47
+ # file :position => [50, 100] { 'README.txt' }
48
+ # Required option:
49
+ # +:position+ - two item array [x, y] window position
50
+ # Options:
51
+ # +:name+ - override the name of the project when mounted in the DMG
52
+ # +:exclude+ - do not include files/folders
53
+ def file(*args, &block)
54
+ path_or_helper, options = args.first.is_a?(Hash) ? [block, args.first] : [args.first, args.last]
55
+ throw "add_files #{path_or_helper}, :position => [x,y] option is missing" unless options[:position]
56
+ @files[path_or_helper] = options
57
+ end
58
+
59
+ # Add the whole project as a mounted item; e.g. a TextMate bundle
60
+ # Examples:
61
+ # add_link "http://github.com/drnic/choctop", :name => 'Github', :position => [50, 100]
62
+ # add_link "http://github.com/drnic/choctop", 'Github.webloc', :position => [50, 100]
63
+ # Required option:
64
+ # +:position+ - two item array [x, y] window position
65
+ # +:name+ - override the name of the project when mounted in the DMG
66
+ def link(url, *options)
67
+ name = options.first if options.first.is_a?(String)
68
+ options = options.last || {}
69
+ options[:url] = url
70
+ options[:name] = name if name
71
+ throw "add_link :position => [x,y] option is missing" unless options[:position]
72
+ throw "add_link :name => 'Name' option is missing" unless options[:name]
73
+ options[:name].gsub!(/(\.webloc|\.url)$/, '')
74
+ options[:name] += ".webloc"
75
+ self.files ||= {}
76
+ files[options[:name]] = options
77
+ end
78
+
79
+ def initialize
80
+ @plist = Plist::parse_xml(File.expand_path('Info.plist'))
81
+ @files = {}
82
+
83
+ yield self if block_given?
84
+
85
+ default
86
+ define_tasks
87
+ end
88
+
89
+ attr_reader :name
90
+ attr_reader :version
91
+ attr_reader :volume_path
92
+ attr_reader :build_path
93
+ attr_reader :pkg_name
94
+ attr_reader :pkg
95
+ attr_reader :dmg_src_folder
96
+ attr_reader :bundle
97
+ attr_reader :volume_background
98
+
99
+ attr_reader :files
100
+
101
+ attr_reader :appcast_filename
102
+ attr_reader :dsa_signature
103
+
104
+ attr_reader :versionless_pkg_name
105
+ attr_reader :pkg_relative_url
106
+
107
+ attr_reader :release_notes_template
108
+ attr_reader :release_notes
109
+
110
+ private
111
+ def default
112
+ @name = @plist['CFBundleExecutable'] || File.basename(File.expand_path("."))
113
+ @name = File.basename(File.expand_path(".")) if @name == '${EXECUTABLE_NAME}'
114
+ @version = @plist['CFBundleVersion']
115
+
116
+ @su_feed_url ||= @plist['SUFeedURL']
117
+ @base_url ||= File.dirname(su_feed_url)
118
+ @host ||= URI.parse(base_url).host
119
+ @release_notes ||= 'release_notes.html'
120
+
121
+ @background_file ||= File.expand_path(File.join(File.dirname(__FILE__), "..", "templates", "default_background.jpg"))
122
+ @app_icon_position ||= [175, 65]
123
+ @applications_icon_position ||= [347, 270]
124
+ @volume_icon ||= File.expand_path(File.join(File.dirname(__FILE__), "..", "templates", "default_volume.icns"))
125
+ @build_type ||= ENV['BUILD_TYPE'] || 'Release'
126
+ @target ||= @name
127
+ @build_options ||= ''
128
+
129
+ @icon_size ||= 104
130
+ @icon_text_size ||= 12
131
+
132
+ @volume_path = "/Volumes/#{@name}"
133
+ @build_path = "appcast/build"
134
+ @pkg_name = "#{@name}-#{@version}.dmg"
135
+ @pkg = "#{@build_path}/#{@pkg_name}"
136
+ @dmg_src_folder = "build/#{@build_type}/dmg"
137
+ @bundle = Dir["build/#{@build_type}/#{@name}.*"].first
138
+ @volume_background = ".background/background#{File.extname(@background_file)}"
139
+ file :bundle, :position => @app_icon_position
140
+
141
+ @appcast_filename ||= su_feed_url ? File.basename(su_feed_url) : 'my_feed.xml'
142
+ @private_key ||= File.expand_path('dsa_priv.pem')
143
+ @dsa_signature ||= `openssl dgst -sha1 -binary < "#{@pkg}" | openssl dgst -dss1 -sign "#{@private_key}" | openssl enc -base64`
144
+
145
+ @versionless_pkg_name = "#{@name}.dmg"
146
+ @pkg_relative_url = "#{@base_url.gsub(%r{/$}, '')}/#{@pkg_name}".gsub(%r{^.*#{@host}}, '')
147
+
148
+ @release_notes_template = "release_notes_template.html.erb"
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require 'chocbomb'
5
+
6
+ ChocBomb::Configuration.new do |s|
7
+ # Custom DMG
8
+ # s.background_file = "background.jpg"
9
+ # s.app_icon_position = [100, 90]
10
+ # s.applications_icon_position = [400, 90]
11
+ # s.volume_icon = "dmg.icns"
12
+ # s.applications_icon = "appicon.icns" # or "appicon.png"
13
+ end
Binary file
Binary file
data/test/helper.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'chocbomb'
7
+
8
+ class Test::Unit::TestCase
9
+ end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ require 'chocbomb/tools/images'
4
+
5
+ class TestChocbomb < Test::Unit::TestCase
6
+ JPG_FILE = File.join(File.dirname(File.expand_path(__FILE__)), 'ressources', 'default_background.jpg')
7
+ PNG_FILE = File.join(File.dirname(File.expand_path(__FILE__)), 'ressources', 'default_background.png')
8
+
9
+ def test_jpg_image_size
10
+ width, height = ChocBomb::Tools::Images.size(JPG_FILE)
11
+ assert_equal(500, width)
12
+ assert_equal(400, height)
13
+ end
14
+
15
+ def test_png_image_size
16
+ width, height = ChocBomb::Tools::Images.size(PNG_FILE)
17
+ assert_equal(500, width)
18
+ assert_equal(400, height)
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chocbomb
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - glejeune
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-25 00:00:00 +01:00
19
+ default_executable: chocbomb
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: plist
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 3
32
+ - 1
33
+ - 0
34
+ version: 3.1.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: escape
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 23
46
+ segments:
47
+ - 0
48
+ - 0
49
+ - 4
50
+ version: 0.0.4
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: builder
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 15
62
+ segments:
63
+ - 2
64
+ - 1
65
+ - 2
66
+ version: 2.1.2
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: RedCloth
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 49
78
+ segments:
79
+ - 4
80
+ - 2
81
+ - 3
82
+ version: 4.2.3
83
+ type: :runtime
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: jeweler
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ hash: 7
94
+ segments:
95
+ - 1
96
+ - 5
97
+ - 2
98
+ version: 1.5.2
99
+ type: :development
100
+ version_requirements: *id005
101
+ - !ruby/object:Gem::Dependency
102
+ name: rcov
103
+ prerelease: false
104
+ requirement: &id006 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ type: :development
114
+ version_requirements: *id006
115
+ description: "ChocBomb is a shameful copy of ChocTop - Build and deploy tools for Cocoa apps using Sparkle for distributions and upgrades; it\xE2\x80\x99s like Hoe but for Cocoa apps."
116
+ email: gregoire.lejeune@gmail.com
117
+ executables:
118
+ - chocbomb
119
+ extensions: []
120
+
121
+ extra_rdoc_files:
122
+ - LICENSE.txt
123
+ - README.rdoc
124
+ files:
125
+ - .document
126
+ - LICENSE.txt
127
+ - README.rdoc
128
+ - Rakefile
129
+ - VERSION
130
+ - bin/chocbomb
131
+ - lib/chocbomb.rb
132
+ - lib/chocbomb/rake/tasks.rb
133
+ - lib/chocbomb/tools/dmg.rb
134
+ - lib/chocbomb/tools/feed.rb
135
+ - lib/chocbomb/tools/images.rb
136
+ - lib/chocbomb/tools/xcode.rb
137
+ - templates/Rakefile.erb
138
+ - templates/default_background.jpg
139
+ - templates/default_volume.icns
140
+ - test/helper.rb
141
+ - test/ressources/default_background.jpg
142
+ - test/ressources/default_background.png
143
+ - test/test_chocbomb.rb
144
+ has_rdoc: true
145
+ homepage: http://github.com/glejeune/chocbomb
146
+ licenses:
147
+ - MIT
148
+ post_install_message:
149
+ rdoc_options: []
150
+
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ hash: 3
159
+ segments:
160
+ - 0
161
+ version: "0"
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ hash: 3
168
+ segments:
169
+ - 0
170
+ version: "0"
171
+ requirements: []
172
+
173
+ rubyforge_project:
174
+ rubygems_version: 1.5.0
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: ChocBomb is a shameful copy of ChocTop
178
+ test_files:
179
+ - test/helper.rb
180
+ - test/test_chocbomb.rb