choctop 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,118 +1,125 @@
1
- module ChocTop::Appcast
2
- def make_build
3
- if skip_build
4
- puts "Skipping build task..."
5
- else
6
- sh "xcodebuild -configuration #{build_type}"
1
+ module ChocTop
2
+ module Appcast
3
+ def make_build
4
+ if skip_build
5
+ puts "Skipping build task..."
6
+ else
7
+ sh "xcodebuild -configuration #{build_type} -target #{build_target} #{build_opts}"
8
+ end
7
9
  end
8
- end
9
-
10
- def make_appcast
11
- app_name = File.basename(File.expand_path('.'))
12
- FileUtils.mkdir_p(build_path)
13
- appcast = File.open("#{build_path}/#{appcast_filename}", 'w') do |f|
14
- xml = Builder::XmlMarkup.new(:indent => 2)
15
- xml.instruct!
16
- xml_string = xml.rss('xmlns:atom' => "http://www.w3.org/2005/Atom",
17
- 'xmlns:sparkle' => "http://www.andymatuschak.org/xml-namespaces/sparkle",
18
- :version => "2.0") do
19
- xml.channel do
20
- xml.title(app_name)
21
- xml.description("#{app_name} updates")
22
- xml.link(base_url)
23
- xml.language('en')
24
- xml.pubDate Time.now.to_s(:rfc822)
25
- # xml.lastBuildDate(Time.now.rfc822)
26
- xml.atom(:link, :href => "#{base_url}/#{appcast_filename}",
27
- :rel => "self", :type => "application/rss+xml")
28
10
 
29
- xml.item do
30
- xml.title("#{name} #{version}")
31
- xml.tag! "sparkle:releaseNotesLink", "#{base_url}/#{release_notes}"
32
- xml.pubDate Time.now.to_s(:rfc822) #(File.mtime(pkg))
33
- xml.guid("#{name}-#{version}", :isPermaLink => "false")
34
- xml.enclosure(:url => "#{base_url}/#{pkg_name}",
35
- :length => "#{File.size(pkg)}",
36
- :type => "application/dmg",
37
- :"sparkle:version" => version,
38
- :"sparkle:dsaSignature" => dsa_signature)
11
+ def make_appcast
12
+ FileUtils.mkdir_p(build_path)
13
+ appcast = File.open("#{build_path}/#{appcast_filename}", 'w') do |f|
14
+ xml = Builder::XmlMarkup.new(:indent => 2)
15
+ xml.instruct!
16
+ xml_string = xml.rss('xmlns:atom' => "http://www.w3.org/2005/Atom",
17
+ 'xmlns:sparkle' => "http://www.andymatuschak.org/xml-namespaces/sparkle",
18
+ :version => "2.0") do
19
+ xml.channel do
20
+ xml.title(@name)
21
+ xml.description("#{@name} updates")
22
+ xml.link(base_url)
23
+ xml.language('en')
24
+ xml.pubDate( Time.now.strftime("%a, %d %b %Y %H:%M:%S %z") )
25
+ # xml.lastBuildDate(Time.now.rfc822)
26
+ xml.atom(:link, :href => "#{base_url}/#{appcast_filename}",
27
+ :rel => "self", :type => "application/rss+xml")
28
+
29
+ xml.item do
30
+ xml.title("#{name} #{version}")
31
+ xml.tag! "sparkle:releaseNotesLink", "#{base_url}/#{release_notes}"
32
+ xml.pubDate Time.now.strftime("%a, %d %b %Y %H:%M:%S %z")
33
+ xml.guid("#{name}-#{version}", :isPermaLink => "false")
34
+ xml.enclosure(:url => "#{base_url}/#{pkg_name}",
35
+ :length => "#{File.size(pkg)}",
36
+ :type => "application/dmg",
37
+ :"sparkle:version" => version,
38
+ :"sparkle:dsaSignature" => dsa_signature)
39
+ end
39
40
  end
40
41
  end
42
+ f << xml_string
41
43
  end
42
- f << xml_string
43
44
  end
44
- end
45
-
46
- def make_dmg_symlink
47
- FileUtils.chdir(build_path) do
48
- `ln -s #{pkg_name} #{versionless_pkg_name}`
45
+
46
+ def make_dmg_symlink
47
+ FileUtils.chdir(build_path) do
48
+ `rm '#{versionless_pkg_name}'`
49
+ `ln -s '#{pkg_name}' '#{versionless_pkg_name}'`
50
+ end
49
51
  end
50
- end
51
-
52
- def make_index_redirect
53
- File.open("#{build_path}/index.php", 'w') do |f|
54
- f << %Q{<?php header("Location: #{pkg_relative_url}"); ?>}
52
+
53
+ def make_index_redirect
54
+ File.open("#{build_path}/index.php", 'w') do |f|
55
+ f << %Q{<?php header("Location: #{pkg_relative_url}"); ?>}
56
+ end
55
57
  end
56
- end
57
-
58
- def skip_build
59
- return true if ENV['NO_BUILD']
60
- return false if File.exists?('Info.plist')
61
- return false if Dir['*.xcodeproj'].size > 0
62
- true
63
- end
64
-
65
- def make_release_notes
66
- File.open("#{build_path}/#{release_notes}", "w") do |f|
67
- template = File.read(release_notes_template)
68
- f << ERB.new(template).result(binding)
58
+
59
+ def skip_build
60
+ return true if ENV['NO_BUILD']
61
+ return false if File.exists?('Info.plist')
62
+ return false if Dir['*.xcodeproj'].size > 0
63
+ true
69
64
  end
70
- end
71
-
72
- def release_notes_content
73
- if File.exists?("release_notes.txt")
74
- File.read("release_notes.txt")
75
- else
76
- <<-TEXTILE.gsub(/^ /, '')
77
- h1. #{version} #{Date.today}
78
-
79
- h2. Another awesome release!
80
- TEXTILE
65
+
66
+ def make_release_notes
67
+ File.open("#{build_path}/#{release_notes}", "w") do |f|
68
+ template = File.read(release_notes_template)
69
+ f << ERB.new(template).result(binding)
70
+ end
81
71
  end
82
- end
83
-
84
- def release_notes_html
85
- RedCloth.new(release_notes_content).to_html
86
- end
87
72
 
88
- def upload_appcast
89
- _host = host.blank? ? "" : "#{host}:"
90
- _user = user.blank? ? "" : "#{user}@"
91
- sh %{rsync #{rsync_args} #{build_path}/ #{_user}#{_host}#{remote_dir}}
92
- end
93
-
94
- # Returns a file path to the dsa_priv.pem file
95
- # If private key + public key haven't been generated yet then
96
- # generate them
97
- def private_key
98
- unless File.exists?('dsa_priv.pem')
99
- puts "Creating new private and public keys for signing the DMG..."
100
- `openssl dsaparam 2048 < /dev/urandom > dsaparam.pem`
101
- `openssl gendsa dsaparam.pem -out dsa_priv.pem`
102
- `openssl dsa -in dsa_priv.pem -pubout -out dsa_pub.pem`
103
- `rm dsaparam.pem`
104
- puts <<-EOS.gsub(/^ /, '')
105
-
106
- WARNING: DO NOT PUT dsa_priv.pem IN YOUR SOURCE CONTROL
107
- Remember to add it to your ignore list
108
-
109
- EOS
73
+ def release_notes_content
74
+ if File.exists?("release_notes.txt")
75
+ File.read("release_notes.txt")
76
+ else
77
+ <<-TEXTILE.gsub(/^ /, '')
78
+ h1. #{version} #{Date.today}
79
+
80
+ h2. Another awesome release!
81
+ TEXTILE
82
+ end
83
+ end
84
+
85
+ def release_notes_html
86
+ RedCloth.new(release_notes_content).to_html
87
+ end
88
+
89
+ def upload_appcast
90
+ _host = host.blank? ? "" : host
91
+ _user = user.blank? ? "" : "#{user}@"
92
+ case transport
93
+ when :scp
94
+ # this is whack, really, work out your rsync options
95
+ sh %{scp #{scp_args} #{build_path}/* #{_user}#{_host}:#{remote_dir}}
96
+ else # default to rsync as per original
97
+ sh %{rsync #{rsync_args} #{build_path}/ #{_user}#{_host}:#{remote_dir}}
98
+ end
99
+ end
100
+
101
+ # Returns a file path to the dsa_priv.pem file
102
+ # If private key + public key haven't been generated yet then
103
+ # generate them
104
+ def private_key
105
+ unless File.exists?('dsa_priv.pem')
106
+ puts "Creating new private and public keys for signing the DMG..."
107
+ `openssl dsaparam 2048 < /dev/urandom > dsaparam.pem`
108
+ `openssl gendsa dsaparam.pem -out dsa_priv.pem`
109
+ `openssl dsa -in dsa_priv.pem -pubout -out dsa_pub.pem`
110
+ `rm dsaparam.pem`
111
+ puts <<-EOS.gsub(/^ /, '')
112
+
113
+ WARNING: DO NOT PUT dsa_priv.pem IN YOUR SOURCE CONTROL
114
+ Remember to add it to your ignore list
115
+
116
+ EOS
117
+ end
118
+ File.expand_path('dsa_priv.pem')
119
+ end
120
+
121
+ def dsa_signature
122
+ @dsa_signature ||= `openssl dgst -sha1 -binary < "#{pkg}" | openssl dgst -dss1 -sign "#{private_key}" | openssl enc -base64`
110
123
  end
111
- File.expand_path('dsa_priv.pem')
112
- end
113
-
114
- def dsa_signature
115
- @dsa_signature ||= `openssl dgst -sha1 -binary < "#{pkg}" | openssl dgst -dss1 -sign "#{private_key}" | openssl enc -base64`
116
124
  end
117
- end
118
- ChocTop.send(:include, ChocTop::Appcast)
125
+ end
@@ -1,189 +1,193 @@
1
- module ChocTop::Dmg
2
- def prepare_files
3
- self.files = files.inject({}) do |files, file|
4
- path_or_helper, options = file
5
- path = case path_or_helper
6
- when Symbol
7
- send path_or_helper
8
- when Proc
9
- path_or_helper.call
10
- else
11
- path_or_helper
1
+ module ChocTop
2
+ module Dmg
3
+ def prepare_files
4
+ self.files = files.inject({}) do |files, file|
5
+ path_or_helper, options = file
6
+ path = case path_or_helper
7
+ when Symbol
8
+ send path_or_helper
9
+ when Proc
10
+ path_or_helper.call
11
+ else
12
+ path_or_helper
13
+ end
14
+ files[path] = options if path && File.exists?(path) && File.basename(path) != '.'
15
+ files
12
16
  end
13
- files[path] = options if path && File.exists?(path) && File.basename(path) != '.'
14
- files
15
17
  end
16
- end
17
-
18
- def copy_files
19
- FileUtils.mkdir_p(dmg_pkg_folder)
20
- files.each do |path, options|
21
- FileUtils.cp_r(path, dmg_pkg_folder)
18
+
19
+ def copy_files
20
+ FileUtils.rm_r(src_folder) if File.exists? src_folder
21
+ FileUtils.mkdir_p(src_folder)
22
+ files.each do |path, options|
23
+ FileUtils.cp_r(path, src_folder)
24
+ end
22
25
  end
23
- end
24
-
25
- def make_dmg
26
- prepare_files
27
- copy_files
28
- FileUtils.mkdir_p build_path
29
- FileUtils.mkdir_p mountpoint # TODO can we remove random mountpoints?
30
- sh "hdiutil create -format UDRW -quiet -volname '#{name}' -srcfolder '#{dmg_pkg_folder}' '#{pkg}'"
31
- sh "hdiutil attach '#{pkg}' -mountpoint '#{volume_path}' -noautoopen -quiet"
32
- sh "bless --folder '#{volume_path}' --openfolder '#{volume_path}'"
33
- sh "sleep 1"
34
-
35
- puts "volume_icon: #{volume_icon.inspect}"
36
- puts "include_applications_icon?: #{include_applications_icon?.inspect}"
37
- configure_volume_icon
38
- configure_applications_icon if include_applications_icon?
39
- configure_dmg_window
40
- end
41
-
42
- def volume_background
43
- ".background/background#{File.extname(background_file)}"
44
- end
45
-
46
- def window_position
47
- [50, 100]
48
- end
49
-
50
- def window_bounds
51
- window_position +
52
- window_position.zip(background_bounds).map { |w, b| w + b }
53
- end
54
-
55
- def background_bounds
56
- return [400, 300] unless background_file
57
- background = OSX::NSImage.alloc.initByReferencingFile(background_file).size.to_a
58
- [background.first, background.last + statusbar_height]
59
- end
60
-
61
- def statusbar_height; 20; end
62
-
63
- def configure_volume_icon
64
- if volume_icon
65
- FileUtils.cp(volume_icon, "#{volume_path}/.VolumeIcon.icns")
66
- sh "SetFile -a C '#{volume_path}'"
26
+
27
+ def make_dmg
28
+ prepare_files
29
+ copy_files
30
+ FileUtils.mkdir_p build_path
31
+ FileUtils.mkdir_p mountpoint # TODO can we remove random mountpoints?
32
+ FileUtils.rm_f(pkg) # make sure destination pkg doesn't already exist, or hdiutil will barf
33
+ sh "hdiutil create -format UDRW -quiet -volname '#{name}' -srcfolder '#{src_folder}' '#{pkg}'"
34
+ sh "hdiutil attach '#{pkg}' -mountpoint '#{volume_path}' -noautoopen -quiet"
35
+ sh "bless --folder '#{volume_path}' --openfolder '#{volume_path}'"
36
+ sh "sleep 1"
37
+
38
+ puts "volume_icon: #{volume_icon.inspect}"
39
+ puts "include_applications_icon?: #{include_applications_icon?.inspect}"
40
+ configure_volume_icon
41
+ configure_applications_icon if include_applications_icon?
42
+ configure_dmg_window
67
43
  end
68
- end
69
44
 
70
- def configure_dmg_window
71
- if background_file
72
- target_background = "#{volume_path}/#{volume_background}"
73
- FileUtils.mkdir_p(File.dirname(target_background))
74
- FileUtils.cp(background_file, target_background)
75
- end
76
- script = <<-SCRIPT.gsub(/^ /, '')
77
- tell application "Finder"
78
- set applications_folder to displayed name of (path to applications folder) -- i18n
79
- set mountpoint to POSIX file ("#{volume_path}" as string) as alias
80
- tell folder mountpoint
81
- open
82
- tell container window
83
- set toolbar visible to false
84
- set statusbar visible to false -- doesn't do anything at DMG open time
85
- set current view to icon view
86
- delay 1 -- Sync
87
- set the bounds to {#{window_bounds.join(", ")}}
88
- end tell
89
- delay 1 -- Sync
90
- set icon size of the icon view options of container window to #{icon_size}
91
- set text size of the icon view options of container window to #{icon_text_size}
92
- set arrangement of the icon view options of container window to not arranged
93
- #{set_position_of_files}
94
- #{set_position_of_shortcuts}
95
- set the bounds of the container window to {#{window_bounds.join(", ")}}
96
- set background picture of the icon view options of container window to file "#{volume_background.gsub(/\//,':')}"
97
- update without registering applications
98
- delay 5 -- Sync
99
- close
100
- end tell
101
- -- Sync
102
- delay 5
103
- end tell
104
- SCRIPT
105
- run_applescript(script)
106
- sh "SetFile -a V '#{target_background}'" if background_file
107
- end
108
-
109
- def set_position_of_files
110
- files.map do |file_options|
111
- path, options = file_options
112
- target = File.basename(path)
113
- position = options[:position].join(", ")
114
- %Q{set position of item "#{target}" to {#{position}}}
115
- end.join("\n")
116
- end
117
-
118
- def set_position_of_shortcuts
119
- if include_applications_icon?
120
- %Q{set position of item applications_folder to {#{applications_icon_position.join(", ")}}}
121
- else
122
- ""
45
+ def volume_background
46
+ ".background/background#{File.extname(background_file)}"
123
47
  end
124
- end
125
-
126
- def include_applications_icon?
127
- puts "target: #{target.inspect}"
128
- target =~ /.app$/
129
- end
130
-
131
- def configure_applications_icon
132
- run_applescript <<-SCRIPT.gsub(/^ /, ''), "apps_icon_script"
133
- tell application "Finder"
134
- set applications_folder to displayed name of (path to applications folder) -- i18n
135
- set dest to disk "#{name}"
136
- set src to folder applications_folder of startup disk
137
- make new alias at dest to src
138
- end tell
139
- SCRIPT
140
- if applications_icon
141
- applications_path = "#{volume_path}/Applications"
142
- OSX::NSApplicationLoad()
143
- image = OSX::NSImage.alloc.initWithContentsOfFile(applications_icon)
144
- OSX::NSWorkspace.sharedWorkspace.setIcon_forFile_options(image, applications_path, nil)
48
+
49
+ def window_position
50
+ [50, 100]
145
51
  end
146
- end
147
-
148
- def detach_dmg
149
- mounted_paths = `hdiutil info | grep '#{volume_path}' | grep "Apple_HFS"`.split("\n").map { |e| e.split(" ").first }
150
- mounted_paths.each do |path|
151
- begin
152
- sh "hdiutil detach '#{path}' -quiet -force"
153
- rescue StandardError => e
154
- p e
52
+
53
+ def window_bounds
54
+ window_position +
55
+ window_position.zip(background_bounds).map { |w, b| w + b }
56
+ end
57
+
58
+ def background_bounds
59
+ return [400, 300] unless background_file
60
+ background = OSX::NSImage.alloc.initByReferencingFile(background_file).size.to_a
61
+ [background.first, background.last + statusbar_height]
62
+ end
63
+
64
+ def statusbar_height; 20; end
65
+
66
+ def configure_volume_icon
67
+ if volume_icon
68
+ FileUtils.cp(volume_icon, "#{volume_path}/.VolumeIcon.icns")
69
+ sh "SetFile -a C '#{volume_path}'"
155
70
  end
156
71
  end
157
- end
158
-
159
- def convert_dmg_readonly
160
- tmp_path = "/tmp/rw.dmg"
161
- FileUtils.mv(pkg, tmp_path)
162
- sh "hdiutil convert '#{tmp_path}' -format UDZO -imagekey zlib-level=9 -o '#{pkg}'"
163
- end
164
-
165
- def add_eula
166
- # TODO support EULA
167
- # hdiutil unflatten $@
168
- # /Developer/Tools/DeRez -useDF SLAResources.rsrc > build/temp/sla.r
169
- # /Developer/Tools/Rez -a build/temp/sla.r -o $@
170
- # hdiutil flatten $@
171
-
172
- end
173
-
174
- def run_applescript(applescript, tmp_file = "choctop-script")
175
- File.open(scriptfile = "/tmp/#{tmp_file}", "w") do |f|
176
- f << applescript
177
- end
178
- sh("osascript #{scriptfile}") do |ok, res|
179
- if ! ok
180
- p res
181
- puts volume_path
182
- exit 1
72
+
73
+ def configure_dmg_window
74
+ if background_file
75
+ target_background = "#{volume_path}/#{volume_background}"
76
+ FileUtils.mkdir_p(File.dirname(target_background))
77
+ FileUtils.cp(background_file, target_background)
183
78
  end
79
+ script = <<-SCRIPT.gsub(/^ /, '')
80
+ tell application "Finder"
81
+ set applications_folder to displayed name of (path to applications folder) -- i18n
82
+ set mountpoint to POSIX file ("#{volume_path}" as string) as alias
83
+ tell folder mountpoint
84
+ open
85
+ tell container window
86
+ set toolbar visible to false
87
+ set statusbar visible to false -- doesn't do anything at DMG open time
88
+ set current view to icon view
89
+ delay 1 -- Sync
90
+ set the bounds to {#{window_bounds.join(", ")}}
91
+ end tell
92
+ delay 1 -- Sync
93
+ set icon size of the icon view options of container window to #{icon_size}
94
+ set text size of the icon view options of container window to #{icon_text_size}
95
+ set arrangement of the icon view options of container window to not arranged
96
+ #{set_position_of_files}
97
+ #{set_position_of_shortcuts}
98
+ close
99
+ open
100
+ set the bounds of the container window to {#{window_bounds.join(", ")}}
101
+ set background picture of the icon view options of container window to file "#{volume_background.gsub(/\//,':')}"
102
+ update without registering applications
103
+ delay 5 -- Sync
104
+ close
105
+ end tell
106
+ -- Sync
107
+ delay 5
108
+ end tell
109
+ SCRIPT
110
+ puts "script: #{script}"
111
+ run_applescript(script)
112
+ sh "SetFile -a V '#{target_background}'" if background_file
184
113
  end
185
- applescript
186
- end
187
- end
188
- ChocTop.send(:include, ChocTop::Dmg)
189
114
 
115
+ def set_position_of_files
116
+ files.map do |file_options|
117
+ path, options = file_options
118
+ target = File.basename(path)
119
+ position = options[:position].join(", ")
120
+ %Q{set position of item "#{target}" to {#{position}}}
121
+ end.join("\n")
122
+ end
123
+
124
+ def set_position_of_shortcuts
125
+ if include_applications_icon?
126
+ %Q{set position of item applications_folder to {#{applications_icon_position.join(", ")}}}
127
+ else
128
+ ""
129
+ end
130
+ end
131
+
132
+ def include_applications_icon?
133
+ target =~ /.app$/
134
+ end
135
+
136
+ def configure_applications_icon
137
+ run_applescript <<-SCRIPT.gsub(/^ /, ''), "apps_icon_script"
138
+ tell application "Finder"
139
+ set applications_folder to displayed name of (path to applications folder) -- i18n
140
+ set dest to disk "#{name}"
141
+ set src to folder applications_folder of startup disk
142
+ make new alias at dest to src
143
+ end tell
144
+ SCRIPT
145
+ if applications_icon
146
+ applications_path = "#{volume_path}/Applications"
147
+ OSX::NSApplicationLoad()
148
+ image = OSX::NSImage.alloc.initWithContentsOfFile(applications_icon)
149
+ OSX::NSWorkspace.sharedWorkspace.setIcon_forFile_options(image, applications_path, nil)
150
+ end
151
+ end
152
+
153
+ def detach_dmg
154
+ mounted_paths = `hdiutil info | grep '#{volume_path}' | grep "Apple_HFS"`.split("\n").map { |e| e.split(" ").first }
155
+ mounted_paths.each do |path|
156
+ begin
157
+ sh "hdiutil detach '#{path}' -quiet -force"
158
+ rescue StandardError => e
159
+ p e
160
+ end
161
+ end
162
+ end
163
+
164
+ def convert_dmg_readonly
165
+ tmp_path = "/tmp/rw.dmg"
166
+ FileUtils.mv(pkg, tmp_path)
167
+ sh "hdiutil convert '#{tmp_path}' -format UDZO -imagekey zlib-level=9 -o '#{pkg}'"
168
+ end
169
+
170
+ def add_eula
171
+ # TODO support EULA
172
+ # hdiutil unflatten $@
173
+ # /Developer/Tools/DeRez -useDF SLAResources.rsrc > build/temp/sla.r
174
+ # /Developer/Tools/Rez -a build/temp/sla.r -o $@
175
+ # hdiutil flatten $@
176
+
177
+ end
178
+
179
+ def run_applescript(applescript, tmp_file = "choctop-script")
180
+ File.open(scriptfile = "/tmp/#{tmp_file}", "w") do |f|
181
+ f << applescript
182
+ end
183
+ sh("osascript #{scriptfile}") do |ok, res|
184
+ if ! ok
185
+ p res
186
+ puts volume_path
187
+ exit 1
188
+ end
189
+ end
190
+ applescript
191
+ end
192
+ end
193
+ end