add command-line plugins

This commit is contained in:
Laurent Sansonetti
2013-05-04 18:59:53 +02:00
parent f0d43a489f
commit c4fc96bff3
8 changed files with 444 additions and 268 deletions

View File

@@ -5,279 +5,16 @@
# Agreement accompanying the package this file is a part of.
require 'fileutils'
require 'uri'
relative_libdir = File.expand_path(File.join(File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__), '../lib'))
$motion_libdir = File.exist?(File.join(relative_libdir, 'motion')) ? relative_libdir : '/Library/RubyMotion/lib'
$:.unshift($motion_libdir)
require 'motion/version'
require 'motion/project/app.rb'
require 'motion/project/builder.rb'
class Command
class << self
attr_accessor :name
attr_accessor :help
def die(*msg)
$stderr.puts msg
exit 1
end
require 'motion/project/command'
def need_root
if Process.uid != 0
die "You need to be root to run this command."
end
end
def read_license_key
unless File.exist?(LicensePath)
die "License file not present. Please activate RubyMotion with `motion activate' and try again."
end
File.read(LicensePath).strip
end
def guess_email_address
# Guess the default email address from git.
URI.escape(`git config --get user.email`.strip)
end
end
command_paths = [File.join($motion_libdir, 'motion/project/command'), File.join(ENV['HOME'], 'Library/RubyMotion/command')]
command_paths.each do |path|
Dir.glob(File.join(path, '*.rb')).each { |x| require x }
end
class CreateCommand < Command
self.name = 'create'
self.help = 'Create a new project'
def self.run(args)
if args.size < 1 || args.size > 2
end
app_name = nil
template_name = 'ios'
args.each do |a|
case a
when /--([^=]+)=(.+)/
opt_name = $1.to_s.strip
opt_val = $2.to_s.strip
case opt_name
when 'template'
template_name = opt_val
else
die "Incorrect option `#{opt_name}'"
end
else
if app_name
app_name = nil
break
else
app_name = a
end
end
end
unless app_name
die "Usage: motion create [--template=<template_name>] <app-name>"
end
Motion::Project::App.create(app_name, template_name)
end
end
LicensePath = '/Library/RubyMotion/license.key'
class ActivateCommand < Command
self.name = 'activate'
self.help = 'Activate the software license'
def self.run(args)
if File.exist?(LicensePath)
die "Product is already activated. Delete the license file `#{LicensePath}' if you want to activate a new license."
end
if args.size != 1
die "Usage: motion activate <license-key>"
end
license_key = args[0]
unless license_key.match(/^[a-f0-9]{40}$/)
die "Given license key `#{license_key}' seems invalid. It should be a string of 40 hexadecimal characters. Check the mail you received after the order, or contact us if you need any help: info@hipbyte.com"
end
need_root
File.open(LicensePath, 'w') { |io| io.write license_key }
puts "Product activated. Thanks for purchasing RubyMotion :-)"
end
end
class AccountCommand < Command
self.name = 'account'
self.help = 'Access the software license account'
def self.run(args)
unless args.empty?
die "Usage: motion account"
end
license_key = read_license_key
email = guess_email_address
system("open \"https://secure.rubymotion.com/account?license_key=#{license_key}&email=#{email}\"")
end
end
class SupportCommand < Command
self.name = 'support'
self.help = 'Create a support ticket'
def self.run(args)
unless args.empty?
die "Usage: motion support"
end
license_key = read_license_key
email = guess_email_address
# Collect details about the environment.
osx_vers = `/usr/bin/sw_vers -productVersion`.strip
rm_vers = Motion::Version
xcode_vers = begin
xcodebuild = `which xcodebuild`.strip
xcodebuild = '/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild' if xcodebuild.empty?
vers = ''
if File.exist?(xcodebuild)
vers = `#{xcodebuild} -version`.strip.scan(/Xcode\s(.+)$/).flatten[0].to_s
end
vers = 'unknown' if vers.empty?
vers
end
environment = URI.escape("OSX #{osx_vers}, RubyMotion #{rm_vers}, Xcode #{xcode_vers}")
system("open \"https://secure.rubymotion.com/new_support_ticket?license_key=#{license_key}&email=#{email}&environment=#{environment}\"")
end
end
class UpdateCommand < Command
self.name = 'update'
self.help = 'Update the software'
def self.curl(cmd)
resp = `/usr/bin/curl --connect-timeout 60 #{cmd}`
if $?.exitstatus != 0
die "Error when connecting to the server. Check your Internet connection and try again."
end
resp
end
def self.run(args)
check_mode = false
wanted_software_version = ''
args.each do |a|
case a
when '--check'
check_mode = true
when /--force-version=(.+)/
wanted_software_version = $1.to_s
else
die "Usage: motion update [--force-version=X]"
end
end
product_version = Motion::Version
if check_mode
update_check_file = File.join(ENV['TMPDIR'] || '/tmp', '.motion-update-check')
if !File.exist?(update_check_file) or (Time.now - File.mtime(update_check_file) > 60 * 60 * 24)
resp = curl("-s -d \"product=rubymotion\" -d \"current_software_version=#{product_version}\" http://secure.rubymotion.com/latest_software_version")
exit 1 unless resp.match(/^\d+\.\d+/)
File.open(update_check_file, 'w') { |io| io.write(resp) }
end
exit File.read(update_check_file) > product_version ? 2 : 0
end
unless File.exist?(LicensePath)
die "License file not present. Please activate RubyMotion with `motion activate' and try again."
end
need_root
license_key = File.read(LicensePath).strip
$stderr.puts "Connecting to the server..."
resp = curl("-s -d \"product=rubymotion\" -d \"current_software_version=#{product_version}\" -d \"wanted_software_version=#{wanted_software_version}\" -d \"license_key=#{license_key}\" https://secure.rubymotion.com/update_software")
unless resp.match(/^http:/)
die resp
end
$stderr.puts "Downloading software update..."
url = resp
tmp_dest = '/tmp/_rubymotion_su.pkg'
curl("-# \"#{url}\" -o #{tmp_dest}")
$stderr.puts "Installing software update..."
installer = "/usr/sbin/installer -pkg \"#{tmp_dest}\" -target / >& /tmp/installer.stderr"
unless system(installer)
die "An error happened when installing the software update: #{File.read('/tmp/installer.stderr')}"
end
FileUtils.rm_f tmp_dest
$stderr.puts "Software update installed.\n\n"
news = File.read('/Library/RubyMotion/NEWS')
news.lines.each do |line|
if md = line.match(/^=\s+RubyMotion\s+(.+)\s+=$/)
break if md[1] <= product_version
end
$stderr.puts line
end
$stderr.puts "(See the `/Library/RubyMotion/NEWS' file for all changes.)"
FileUtils.rm_rf Motion::Project::Builder.common_build_dir
end
end
class RICommand < Command
self.name = 'ri'
self.help = 'Display API reference'
def self.run(args)
if args.size <= 0
die "Usage: motion ri <API-name>"
end
system("/Library/RubyMotion/lib/yard/bin/yri --db /Library/RubyMotion/doc/yardoc #{args[0]}")
end
end
class MotionMainCommand
Commands = [CreateCommand, ActivateCommand, UpdateCommand, RICommand, SupportCommand, AccountCommand]
def initialize(args)
arg = args.shift
case arg
when '-h', '--help'
usage
when '-v', '--version'
$stdout.puts Motion::Version
exit 1
when /^-/
$stderr.puts "Unknown option: #{arg}"
exit 1
end
command = Commands.find { |command| command.name == arg }
usage unless command
command.run(args)
end
def usage
$stderr.puts 'Usage:'
$stderr.puts " #{File.basename(__FILE__)} [-h, --help]"
$stderr.puts " #{File.basename(__FILE__)} [-v, --version]"
$stderr.puts " #{File.basename(__FILE__)} <command> [<args...>]"
$stderr.puts ''
$stderr.puts 'Commands:'
Commands.each do |command|
$stderr.puts " #{command.name}".ljust(15) + command.help
end
exit 1
end
end
MotionMainCommand.new(ARGV)
Motion::Project::Command.main(ARGV)

View File

@@ -0,0 +1,96 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'motion/version'
module Motion; module Project
class Command
class << self
attr_accessor :name
attr_accessor :help
end
Commands = []
def self.inherited(klass)
Commands << klass if self == Command
end
def self.main(args)
arg = args.shift
case arg
when '-h', '--help'
usage
when '-v', '--version'
$stdout.puts Motion::Version
exit 1
when /^-/
$stderr.puts "Unknown option: #{arg}"
exit 1
end
command = Commands.find { |command| command.name == arg }
usage unless command
command.new.run(args)
end
def self.usage
$stderr.puts 'Usage:'
$stderr.puts " motion [-h, --help]"
$stderr.puts " motion [-v, --version]"
$stderr.puts " motion <command> [<args...>]"
$stderr.puts ''
$stderr.puts 'Commands:'
Commands.each do |command|
$stderr.puts " #{command.name}".ljust(15) + command.help
end
exit 1
end
def run(args)
# To be implemented by subclasses.
end
def die(*msg)
$stderr.puts msg
exit 1
end
def need_root
if Process.uid != 0
die "You need to be root to run this command."
end
end
LicensePath = '/Library/RubyMotion/license.key'
def read_license_key
unless File.exist?(LicensePath)
die "License file not present. Please activate RubyMotion with `motion activate' and try again."
end
File.read(LicensePath).strip
end
def guess_email_address
# Guess the default email address from git.
URI.escape(`git config --get user.email`.strip)
end
end
end; end

View File

@@ -0,0 +1,40 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Motion; module Project
class AccountCommand < Command
self.name = 'account'
self.help = 'Access the software license account'
def run(args)
unless args.empty?
die "Usage: motion account"
end
license_key = read_license_key
email = guess_email_address
system("open \"https://secure.rubymotion.com/account?license_key=#{license_key}&email=#{email}\"")
end
end
end; end

View File

@@ -0,0 +1,48 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Motion; module Project
class ActivateCommand < Command
self.name = 'activate'
self.help = 'Activate the software license'
def run(args)
if File.exist?(LicensePath)
die "Product is already activated. Delete the license file `#{LicensePath}' if you want to activate a new license."
end
if args.size != 1
die "Usage: motion activate <license-key>"
end
license_key = args[0]
unless license_key.match(/^[a-f0-9]{40}$/)
die "Given license key `#{license_key}' seems invalid. It should be a string of 40 hexadecimal characters. Check the mail you received after the order, or contact us if you need any help: info@hipbyte.com"
end
need_root
File.open(LicensePath, 'w') { |io| io.write license_key }
puts "Product activated. Thanks for purchasing RubyMotion :-)"
end
end
end; end

View File

@@ -0,0 +1,62 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'motion/project/app'
module Motion; module Project
class CreateCommand < Command
self.name = 'create'
self.help = 'Create a new project'
def run(args)
app_name = nil
template_name = 'ios'
args.each do |a|
case a
when /--([^=]+)=(.+)/
opt_name = $1.to_s.strip
opt_val = $2.to_s.strip
case opt_name
when 'template'
template_name = opt_val
else
die "Incorrect option `#{opt_name}'"
end
else
if app_name
app_name = nil
break
else
app_name = a
end
end
end
unless app_name
die "Usage: motion create [--template=<template_name>] <app-name>"
end
Motion::Project::App.create(app_name, template_name)
end
end
end; end

View File

@@ -0,0 +1,37 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Motion; module Project
class RICommand < Command
self.name = 'ri'
self.help = 'Display API reference'
def run(args)
if args.size <= 0
die "Usage: motion ri <API-name>"
end
system("/Library/RubyMotion/lib/yard/bin/yri --db /Library/RubyMotion/doc/yardoc #{args[0]}")
end
end
end; end

View File

@@ -0,0 +1,58 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'uri'
module Motion; module Project
class SupportCommand < Command
self.name = 'support'
self.help = 'Create a support ticket'
def run(args)
unless args.empty?
die "Usage: motion support"
end
license_key = read_license_key
email = guess_email_address
# Collect details about the environment.
osx_vers = `/usr/bin/sw_vers -productVersion`.strip
rm_vers = Motion::Version
xcode_vers = begin
xcodebuild = `which xcodebuild`.strip
xcodebuild = '/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild' if xcodebuild.empty?
vers = ''
if File.exist?(xcodebuild)
vers = `#{xcodebuild} -version`.strip.scan(/Xcode\s(.+)$/).flatten[0].to_s
end
vers = 'unknown' if vers.empty?
vers
end
environment = URI.escape("OSX #{osx_vers}, RubyMotion #{rm_vers}, Xcode #{xcode_vers}")
system("open \"https://secure.rubymotion.com/new_support_ticket?license_key=#{license_key}&email=#{email}&environment=#{environment}\"")
end
end
end; end

View File

@@ -0,0 +1,98 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'motion/project/builder'
module Motion; module Project
class UpdateCommand < Command
self.name = 'update'
self.help = 'Update the software'
def curl(cmd)
resp = `/usr/bin/curl --connect-timeout 60 #{cmd}`
if $?.exitstatus != 0
die "Error when connecting to the server. Check your Internet connection and try again."
end
resp
end
def run(args)
check_mode = false
wanted_software_version = ''
args.each do |a|
case a
when '--check'
check_mode = true
when /--force-version=(.+)/
wanted_software_version = $1.to_s
else
die "Usage: motion update [--force-version=X]"
end
end
product_version = Motion::Version
if check_mode
update_check_file = File.join(ENV['TMPDIR'] || '/tmp', '.motion-update-check')
if !File.exist?(update_check_file) or (Time.now - File.mtime(update_check_file) > 60 * 60 * 24)
resp = curl("-s -d \"product=rubymotion\" -d \"current_software_version=#{product_version}\" http://secure.rubymotion.com/latest_software_version")
exit 1 unless resp.match(/^\d+\.\d+/)
File.open(update_check_file, 'w') { |io| io.write(resp) }
end
exit File.read(update_check_file) > product_version ? 2 : 0
end
license_key = read_license_key
need_root
$stderr.puts "Connecting to the server..."
resp = curl("-s -d \"product=rubymotion\" -d \"current_software_version=#{product_version}\" -d \"wanted_software_version=#{wanted_software_version}\" -d \"license_key=#{license_key}\" https://secure.rubymotion.com/update_software")
unless resp.match(/^http:/)
die resp
end
$stderr.puts "Downloading software update..."
url = resp
tmp_dest = '/tmp/_rubymotion_su.pkg'
curl("-# \"#{url}\" -o #{tmp_dest}")
$stderr.puts "Installing software update..."
installer = "/usr/sbin/installer -pkg \"#{tmp_dest}\" -target / >& /tmp/installer.stderr"
unless system(installer)
die "An error happened when installing the software update: #{File.read('/tmp/installer.stderr')}"
end
FileUtils.rm_f tmp_dest
$stderr.puts "Software update installed.\n\n"
news = File.read('/Library/RubyMotion/NEWS')
news.lines.each do |line|
if md = line.match(/^=\s+RubyMotion\s+(.+)\s+=$/)
break if md[1] <= product_version
end
$stderr.puts line
end
$stderr.puts "(See the `/Library/RubyMotion/NEWS' file for all changes.)"
FileUtils.rm_rf Motion::Project::Builder.common_build_dir
end
end
end; end