motion-sparkle-sandbox 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +260 -0
- data/Rakefile +8 -0
- data/lib/motion-sparkle-sandbox.rb +11 -0
- data/lib/motion/project/appcast.rb +127 -0
- data/lib/motion/project/appcast/release_notes.content.html +22 -0
- data/lib/motion/project/appcast/release_notes.template.erb +19 -0
- data/lib/motion/project/install.rb +75 -0
- data/lib/motion/project/package.rb +44 -0
- data/lib/motion/project/project.rb +59 -0
- data/lib/motion/project/rake_tasks.rb +89 -0
- data/lib/motion/project/setup.rb +96 -0
- data/lib/motion/project/sparkle.rb +189 -0
- data/lib/motion/project/templates.rb +34 -0
- data/motion-sparkle-sandbox.gemspec +21 -0
- data/spec/sparkle_spec.rb +90 -0
- data/spec/spec_helper.rb +35 -0
- data/vendor/README.md +24 -0
- data/vendor/Sparkle.zip +0 -0
- data/vendor/codesign_xpc +46 -0
- data/vendor/generate_appcast +0 -0
- metadata +67 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
<h1>Your app - version x.yz</h1>
|
2
|
+
|
3
|
+
<h2>The greatest update ever</h2>
|
4
|
+
|
5
|
+
<dl>
|
6
|
+
<dt>An interface to drool for</dt>
|
7
|
+
<dd>I won't say too much (wouldn't want to spoil the surprise)</dd>
|
8
|
+
<dt>Record-breaking performance</dt>
|
9
|
+
<dd>
|
10
|
+
<p>
|
11
|
+
We keep doing it every time and you start to be less impressed, but we're still very proud of ourselves! We could write about our performance for hours, and make you read it for days!
|
12
|
+
</p>
|
13
|
+
<p>
|
14
|
+
<strong>What for?</strong>
|
15
|
+
<br>
|
16
|
+
This does serve a purpose, however, and it is to show you how a longer text would look like. It'll help you figure out your style.
|
17
|
+
</p>
|
18
|
+
<p>
|
19
|
+
Just do the same for your app now :)
|
20
|
+
</p>
|
21
|
+
</dd>
|
22
|
+
</dl>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Release Notes for <%= @config.name %></title>
|
4
|
+
<style>
|
5
|
+
* { font-family: "Helvetica Neue", "Helvetica", "Arial", "Sans";}
|
6
|
+
h1 { background-color: #ABABFF; padding: 10px;}
|
7
|
+
h1 span { font-size: 75%; font-weight: normal; float: right;}
|
8
|
+
dt { font-size: 105%; font-weight: bold; margin: 5px 0;}
|
9
|
+
dd { margin: 0; padding: 5px 0 0 5px; }
|
10
|
+
dd p {margin: 2px 0; padding: 0;}
|
11
|
+
</style>
|
12
|
+
</head>
|
13
|
+
|
14
|
+
<body>
|
15
|
+
|
16
|
+
<%= release_notes_html %>
|
17
|
+
|
18
|
+
</body>
|
19
|
+
</html>
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Motion::Project
|
2
|
+
class Sparkle
|
3
|
+
|
4
|
+
SPARKLE_ZIP_FILE = 'Sparkle.zip'
|
5
|
+
|
6
|
+
def sparkle_distrib
|
7
|
+
file_path = Pathname.new File.dirname(__FILE__)
|
8
|
+
distrib_path = "vendor/#{SPARKLE_ZIP_FILE}"
|
9
|
+
(file_path.parent.parent.parent + distrib_path).to_s
|
10
|
+
Pathname.new(sparkle_vendor_path + SPARKLE_ZIP_FILE)
|
11
|
+
end
|
12
|
+
|
13
|
+
def sparkle_vendor_path
|
14
|
+
file_path = Pathname.new File.dirname(__FILE__)
|
15
|
+
(file_path.parent.parent.parent + 'vendor/').to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def sparkle_path
|
19
|
+
Pathname.new(vendor_path + 'Sparkle')
|
20
|
+
end
|
21
|
+
|
22
|
+
def sparkle_framework_path
|
23
|
+
Pathname.new(vendor_path + 'Sparkle/Sparkle.framework')
|
24
|
+
end
|
25
|
+
|
26
|
+
def sparkle_xpc_path
|
27
|
+
Pathname.new(vendor_path + 'Sparkle/XPCServices')
|
28
|
+
end
|
29
|
+
|
30
|
+
def sparkle_zipball
|
31
|
+
Pathname.new(vendor_path + SPARKLE_ZIP_FILE)
|
32
|
+
end
|
33
|
+
|
34
|
+
def copy_zipball
|
35
|
+
`cp #{sparkle_distrib} #{sparkle_zipball}`
|
36
|
+
end
|
37
|
+
|
38
|
+
def unzip
|
39
|
+
`unzip #{sparkle_zipball.to_s} -d #{vendor_path.to_s}`
|
40
|
+
`rm #{sparkle_zipball}`
|
41
|
+
end
|
42
|
+
|
43
|
+
def installed?
|
44
|
+
File.directory?(sparkle_framework_path)
|
45
|
+
end
|
46
|
+
|
47
|
+
def install
|
48
|
+
FileUtils.rm_rf(sparkle_path) if File.directory?(sparkle_path) # force clean install
|
49
|
+
copy_zipball
|
50
|
+
unzip
|
51
|
+
end
|
52
|
+
|
53
|
+
def embed
|
54
|
+
@config.embedded_frameworks << sparkle_framework_path
|
55
|
+
end
|
56
|
+
|
57
|
+
def install_and_embed
|
58
|
+
install unless installed?
|
59
|
+
embed
|
60
|
+
end
|
61
|
+
|
62
|
+
def verify_installation
|
63
|
+
if installed?
|
64
|
+
App.info "Sparkle", "Framework installed in #{sparkle_framework_path.to_s}"
|
65
|
+
else
|
66
|
+
App.fail "Sparkle framework not correctly copied to #{sparkle_framework_path.to_s}
|
67
|
+
Run `rake sparkle:install` manually or, if the problem persists,
|
68
|
+
please explain your setup and problem as an issue on GitHub at:
|
69
|
+
https://github.com/digitalmoksha/motion-sparkle-sandbox/issues
|
70
|
+
"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Motion::Project
|
2
|
+
class Sparkle
|
3
|
+
|
4
|
+
def package
|
5
|
+
return unless setup_ok?
|
6
|
+
create_release_folder
|
7
|
+
@config.build_mode = :release
|
8
|
+
return unless create_zip_file
|
9
|
+
App.info "Release", version_string
|
10
|
+
App.info "Version", @config.short_version
|
11
|
+
App.info "Build", @config.version || 'unspecified in Rakefile'
|
12
|
+
App.info "Size", @package_size.to_s
|
13
|
+
sign_package
|
14
|
+
create_appcast
|
15
|
+
create_release_notes
|
16
|
+
`open #{sparkle_release_path}`
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_zip_file
|
20
|
+
unless File.exist?(app_bundle_path)
|
21
|
+
App.fail "You need to build your app with the Release target to use Sparkle"
|
22
|
+
end
|
23
|
+
if File.exist?("#{sparkle_release_path}/#{zip_file}")
|
24
|
+
App.fail "Release already exists at ./#{sparkle_release_path}/#{zip_file} (remove it manually with `rake sparkle:clean`)"
|
25
|
+
end
|
26
|
+
FileUtils.cd(app_release_path) do
|
27
|
+
`zip -r --symlinks "#{zip_file}" "#{app_file}"`
|
28
|
+
end
|
29
|
+
FileUtils.mv "#{app_release_path}/#{zip_file}", "./#{sparkle_release_path}/"
|
30
|
+
App.info "Create", "./#{sparkle_release_path}/#{zip_file}"
|
31
|
+
@package_file = zip_file
|
32
|
+
@package_size = File.size "./#{sparkle_release_path}/#{zip_file}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def sign_package
|
36
|
+
package = "./#{sparkle_release_path}/#{zip_file}"
|
37
|
+
@package_signature = `#{openssl} dgst -sha1 -binary < "#{package}" | #{openssl} dgst -dss1 -sign "#{private_key_path}" | #{openssl} enc -base64`
|
38
|
+
@package_signature = @package_signature.strip
|
39
|
+
App.info "Signature", "\"#{@package_signature}\""
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Motion::Project
|
2
|
+
|
3
|
+
class Config
|
4
|
+
variable :sparkle
|
5
|
+
|
6
|
+
def sparkle(&block)
|
7
|
+
@sparkle ||= Motion::Project::Sparkle.new(self)
|
8
|
+
if block
|
9
|
+
@sparkle.instance_eval &block
|
10
|
+
end
|
11
|
+
@sparkle
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class App
|
16
|
+
class << self
|
17
|
+
def build_with_sparkle(platform, opts = {})
|
18
|
+
if App.config.sparkle.setup_ok?
|
19
|
+
App.info "Sparkle", "Setup OK"
|
20
|
+
else
|
21
|
+
exit 1
|
22
|
+
end
|
23
|
+
build_without_sparkle(platform, opts)
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method "build_without_sparkle", "build"
|
27
|
+
alias_method "build", "build_with_sparkle"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Builder
|
32
|
+
|
33
|
+
# if we're using the sandboxed version of Sparkle, then we need to copy the
|
34
|
+
# xpc services to the proper folder and sign them. This has to be done
|
35
|
+
# before we sign the app itself
|
36
|
+
#------------------------------------------------------------------------------
|
37
|
+
def codesign_with_sparkle(config, platform)
|
38
|
+
if App.config.embedded_frameworks.any? {|item| item.to_s.include?('Sparkle.framework')}
|
39
|
+
bundle_path = App.config.app_bundle('MacOSX')
|
40
|
+
if File.directory?(App.config.sparkle.sparkle_xpc_path)
|
41
|
+
xpc_path = File.join(bundle_path, "XPCServices")
|
42
|
+
App.info 'Sparkle', "Copying XPCServices to #{xpc_path}"
|
43
|
+
FileUtils.mkdir_p(xpc_path)
|
44
|
+
`cp -R #{App.config.sparkle.sparkle_xpc_path}/*.xpc "#{xpc_path}"`
|
45
|
+
|
46
|
+
Dir.glob("#{xpc_path}/*.xpc").each do |path|
|
47
|
+
App.info 'Codesign', path
|
48
|
+
results = `#{App.config.sparkle.sparkle_vendor_path}/codesign_xpc "#{App.config.codesign_certificate}" "#{File.expand_path(path)}" 2>&1`
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
codesign_without_sparkle(config, platform)
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method "codesign_without_sparkle", "codesign"
|
56
|
+
alias_method "codesign", "codesign_with_sparkle"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Rake tasks
|
2
|
+
namespace :sparkle do
|
3
|
+
|
4
|
+
task :install do
|
5
|
+
sparkle = App.config.sparkle
|
6
|
+
sparkle.install
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Setup Sparkle configuration"
|
10
|
+
task :setup do
|
11
|
+
sparkle = App.config.sparkle
|
12
|
+
sparkle.setup
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Create a ZIP file with you application .app release build"
|
16
|
+
task :package do
|
17
|
+
App.config_without_setup.build_mode = :release
|
18
|
+
sparkle = App.config.sparkle
|
19
|
+
sparkle.package
|
20
|
+
end
|
21
|
+
|
22
|
+
task :setup_certificates do
|
23
|
+
sparkle = App.config.sparkle
|
24
|
+
sparkle.generate_keys
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Sign the ZIP file with appropriate certificates"
|
28
|
+
task :sign do
|
29
|
+
App.config_without_setup.build_mode = :release
|
30
|
+
sparkle = App.config.sparkle
|
31
|
+
sparkle.sign_package
|
32
|
+
end
|
33
|
+
|
34
|
+
task :recreate_public_key do
|
35
|
+
sparkle = App.config.sparkle
|
36
|
+
sparkle.generate_public_key
|
37
|
+
end
|
38
|
+
|
39
|
+
task :copy_release_notes_templates do
|
40
|
+
App.config_without_setup.build_mode = :release
|
41
|
+
sparkle = App.config.sparkle
|
42
|
+
sparkle.copy_templates(force = true)
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Generate the appcast xml feed"
|
46
|
+
task :feed do
|
47
|
+
App.config_without_setup.build_mode = :release
|
48
|
+
sparkle = App.config.sparkle
|
49
|
+
sparkle.create_appcast
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Generate the appcast using Sparkle's `generate_appcast`"
|
53
|
+
task :generate_appcast do
|
54
|
+
App.config_without_setup.build_mode = :release
|
55
|
+
sparkle = App.config.sparkle
|
56
|
+
results = `#{sparkle.sparkle_vendor_path}/generate_appcast "#{sparkle.private_key_path}" "#{sparkle.archive_folder}"`
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Update the release notes of this build"
|
60
|
+
task :release_notes do
|
61
|
+
App.config_without_setup.build_mode = :release
|
62
|
+
sparkle = App.config.sparkle
|
63
|
+
sparkle.create_release_notes
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Upload to configured location"
|
67
|
+
task :upload do
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Clean the Sparkle release folder"
|
71
|
+
task :clean do
|
72
|
+
dir = Motion::Project::Sparkle::RELEASE_PATH
|
73
|
+
if File.exist?("./#{dir}")
|
74
|
+
App.info 'Delete', "./#{dir}"
|
75
|
+
rm_rf dir
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
namespace :clean do
|
81
|
+
# Delete Sparkle release folder when cleaning all
|
82
|
+
task :all do
|
83
|
+
dir = Motion::Project::Sparkle::RELEASE_PATH
|
84
|
+
if File.exist?("./#{dir}")
|
85
|
+
App.info 'Delete', "./#{dir}"
|
86
|
+
rm_rf dir
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Motion::Project
|
2
|
+
class Sparkle
|
3
|
+
|
4
|
+
def setup_ok?
|
5
|
+
config_ok?
|
6
|
+
certificates_ok?
|
7
|
+
end
|
8
|
+
|
9
|
+
def config_ok?
|
10
|
+
check_base_url
|
11
|
+
check_feed_url
|
12
|
+
check_public_key
|
13
|
+
end
|
14
|
+
|
15
|
+
def check_base_url
|
16
|
+
base_url_check = appcast.base_url.to_s
|
17
|
+
if base_url_check.nil? or base_url_check.empty?
|
18
|
+
App.fail "Sparkle :base_url missing. Use `release :base_url, 'http://example.com/your_app_folder'` in your Rakefile's `app.sparkle` block"
|
19
|
+
end
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_feed_url
|
24
|
+
feed_url_check = @config.info_plist['SUFeedURL']
|
25
|
+
feed_filename_check = appcast.feed_filename
|
26
|
+
if feed_url_check.nil? or feed_url_check.empty? or feed_filename_check.nil? or feed_filename_check.empty?
|
27
|
+
App.fail "Sparkle :feed_filename is nil or blank. Please check your Rakefile."
|
28
|
+
end
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_public_key
|
33
|
+
public_key_check = @config.info_plist['SUPublicDSAKeyFile'].to_s
|
34
|
+
if public_key_check.nil? or public_key_check.empty?
|
35
|
+
App.fail "Sparkle :public_key is nil or blank. Please check your Rakefile."
|
36
|
+
end
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def certificates_ok?(silence=false)
|
41
|
+
unless File.exist?("./#{Sparkle::CONFIG_PATH}")
|
42
|
+
if silence
|
43
|
+
return false
|
44
|
+
else
|
45
|
+
App.fail "Missing `#{Sparkle::CONFIG_PATH}`. Run `rake sparkle:setup` to get started"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
unless File.exist?(private_key_path)
|
49
|
+
if silence
|
50
|
+
return false
|
51
|
+
else
|
52
|
+
App.fail "Missing `#{private_key_path}`. Please run `rake sparkle:setup_certificates` or check the docs to know where to put them."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
unless File.exist?(public_key_path)
|
56
|
+
if silence
|
57
|
+
return false
|
58
|
+
else
|
59
|
+
App.fail "Missing `#{public_key_path}`. Did you configure `release :public_key` correctly in the Rakefile? Advanced: recreate your public key with `rake sparkle:recreate_public_key`"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup
|
66
|
+
verify_installation
|
67
|
+
create_sparkle_folder
|
68
|
+
add_to_gitignore
|
69
|
+
copy_templates
|
70
|
+
|
71
|
+
if config_ok?
|
72
|
+
App.info "Sparkle", "Config found"
|
73
|
+
else
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
|
77
|
+
silence = true
|
78
|
+
if certificates_ok?(silence)
|
79
|
+
App.info "Sparkle", "Certificates found"
|
80
|
+
else
|
81
|
+
App.info "Sparkle", "Certificates not found
|
82
|
+
Please generate your private and public keys with
|
83
|
+
`rake sparkle:setup_certificates`
|
84
|
+
If you already have your certificates and only need to include them in the project, follow these steps:
|
85
|
+
1. Rename your private key to `./#{private_key_path}`
|
86
|
+
2. Place your public key in `./#{public_key_path}`
|
87
|
+
3. If you wish to use a different name or location for your public key within the resources dir,
|
88
|
+
make sure you add `publish :public_key, 'folder/new_name.pem'` to the sparkle config in your Rakefile
|
89
|
+
"
|
90
|
+
return false
|
91
|
+
end
|
92
|
+
App.info "Sparkle", "Setup OK. After `rake build:release`, you can now run `rake sparkle:package`."
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module Motion::Project
|
2
|
+
class Sparkle
|
3
|
+
|
4
|
+
SPARKLE_ROOT = "sparkle"
|
5
|
+
CONFIG_PATH = "#{SPARKLE_ROOT}/config"
|
6
|
+
RELEASE_PATH = "#{SPARKLE_ROOT}/release"
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
publish :public_key, 'dsa_pub.pem'
|
11
|
+
install_and_embed
|
12
|
+
end
|
13
|
+
|
14
|
+
def appcast
|
15
|
+
@appcast ||= Appcast.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def publish(key, value)
|
19
|
+
case key
|
20
|
+
when :public_key
|
21
|
+
public_key value
|
22
|
+
when :base_url
|
23
|
+
appcast.base_url = value
|
24
|
+
feed_url appcast.feed_url
|
25
|
+
when :feed_base_url
|
26
|
+
appcast.feed_base_url = value
|
27
|
+
feed_url appcast.feed_url
|
28
|
+
when :feed_filename
|
29
|
+
appcast.feed_filename = value
|
30
|
+
feed_url appcast.feed_url
|
31
|
+
when :version
|
32
|
+
version value
|
33
|
+
when :notes_base_url, :package_base_url, :notes_filename, :package_filename
|
34
|
+
appcast.send "#{key}=", value
|
35
|
+
when :archive_folder
|
36
|
+
appcast.archive_folder = value
|
37
|
+
else
|
38
|
+
raise "Unknown Sparkle config option #{key}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias_method :release, :publish
|
42
|
+
|
43
|
+
def version(vstring)
|
44
|
+
@config.version = vstring.to_s
|
45
|
+
@config.short_version = vstring.to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
def version_string
|
49
|
+
"#{@config.short_version} (#{@config.version})"
|
50
|
+
end
|
51
|
+
|
52
|
+
def feed_url(url)
|
53
|
+
@config.info_plist['SUFeedURL'] = url
|
54
|
+
end
|
55
|
+
|
56
|
+
def public_key(path_in_resources_folder)
|
57
|
+
@config.info_plist['SUPublicDSAKeyFile'] = path_in_resources_folder
|
58
|
+
end
|
59
|
+
|
60
|
+
# File manipulation and certificates
|
61
|
+
|
62
|
+
def add_to_gitignore
|
63
|
+
@ignorable = ['sparkle/release','sparkle/release/*','sparkle/config/dsa_priv.pem']
|
64
|
+
return unless File.exist?(gitignore_path)
|
65
|
+
File.open(gitignore_path, 'r') do |f|
|
66
|
+
f.each_line do |line|
|
67
|
+
@ignorable.delete(line) if @ignorable.include?(line)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
File.open(gitignore_path, 'a') do |f|
|
71
|
+
@ignorable.each do |i|
|
72
|
+
f << "#{i}\n"
|
73
|
+
end
|
74
|
+
end if @ignorable.any?
|
75
|
+
`cat #{gitignore_path}`
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_sparkle_folder
|
79
|
+
create_config_folder
|
80
|
+
create_release_folder
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_config_folder
|
84
|
+
FileUtils.mkdir_p(sparkle_config_path) unless File.exist?(sparkle_config_path)
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_release_folder
|
88
|
+
FileUtils.mkdir_p(sparkle_release_path) unless File.exist?(sparkle_release_path)
|
89
|
+
end
|
90
|
+
|
91
|
+
def generate_keys
|
92
|
+
return false unless config_ok?
|
93
|
+
unless File.exist?(sparkle_config_path)
|
94
|
+
FileUtils.mkdir_p sparkle_config_path
|
95
|
+
end
|
96
|
+
[dsa_param_path, private_key_path, public_key_path].each do |file|
|
97
|
+
if File.exist? file
|
98
|
+
App.info "Sparkle", "Error: file exists.
|
99
|
+
There's already a '#{file}'. Be careful not to override or lose your certificates. \n
|
100
|
+
Delete this file if you're sure. \n
|
101
|
+
Aborting (no action performed)
|
102
|
+
"
|
103
|
+
return
|
104
|
+
end
|
105
|
+
end
|
106
|
+
`#{openssl} dsaparam 2048 < /dev/urandom > #{dsa_param_path}`
|
107
|
+
`#{openssl} gendsa #{dsa_param_path} -out #{private_key_path}`
|
108
|
+
generate_public_key
|
109
|
+
`rm #{dsa_param_path}`
|
110
|
+
App.info "Sparkle", "Generated private and public certificates.
|
111
|
+
Details:
|
112
|
+
* Private certificate: ./#{private_key_path}
|
113
|
+
* Public certificate: ./#{public_key_path}
|
114
|
+
Warning:
|
115
|
+
ADD YOUR PRIVATE CERTIFICATE TO YOUR `.gitignore` OR EQUIVALENT AND BACK IT UP!
|
116
|
+
KEEP IT PRIVATE AND SAFE!
|
117
|
+
If you lose it, your users will be unable to upgrade.
|
118
|
+
"
|
119
|
+
end
|
120
|
+
|
121
|
+
def generate_public_key
|
122
|
+
`#{openssl} dsa -in #{private_key_path} -pubout -out #{public_key_path}`
|
123
|
+
end
|
124
|
+
|
125
|
+
# A few helpers
|
126
|
+
|
127
|
+
def openssl
|
128
|
+
"/usr/bin/openssl"
|
129
|
+
end
|
130
|
+
|
131
|
+
def project_path
|
132
|
+
@project_path ||= Pathname.new(@config.project_dir)
|
133
|
+
end
|
134
|
+
|
135
|
+
def vendor_path
|
136
|
+
@vendor_path ||= Pathname.new(project_path + 'vendor/')
|
137
|
+
end
|
138
|
+
|
139
|
+
def gitignore_path
|
140
|
+
project_path + ".gitignore"
|
141
|
+
end
|
142
|
+
|
143
|
+
def sparkle_release_path
|
144
|
+
project_path + RELEASE_PATH
|
145
|
+
end
|
146
|
+
|
147
|
+
def sparkle_config_path
|
148
|
+
project_path + CONFIG_PATH
|
149
|
+
end
|
150
|
+
|
151
|
+
def dsa_param_path
|
152
|
+
sparkle_config_path + "dsaparam.pem"
|
153
|
+
end
|
154
|
+
|
155
|
+
def private_key_path
|
156
|
+
sparkle_config_path + "dsa_priv.pem"
|
157
|
+
end
|
158
|
+
|
159
|
+
def public_key_path
|
160
|
+
pub_key_file = @config.info_plist['SUPublicDSAKeyFile']
|
161
|
+
project_path + "resources/#{pub_key_file}"
|
162
|
+
end
|
163
|
+
|
164
|
+
def app_bundle_path
|
165
|
+
Pathname.new @config.app_bundle_raw('MacOSX')
|
166
|
+
end
|
167
|
+
|
168
|
+
def app_release_path
|
169
|
+
app_bundle_path.parent.to_s
|
170
|
+
end
|
171
|
+
|
172
|
+
def app_name
|
173
|
+
File.basename(app_bundle_path, '.app')
|
174
|
+
end
|
175
|
+
|
176
|
+
def zip_file
|
177
|
+
appcast.package_filename || "#{app_name}.zip"
|
178
|
+
end
|
179
|
+
|
180
|
+
def archive_folder
|
181
|
+
appcast.archive_folder
|
182
|
+
end
|
183
|
+
|
184
|
+
def app_file
|
185
|
+
"#{app_name}.app"
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|