Files
RubyMotion/bin/motion
Watson 6f48fd5d0b change the build directory for outside files of project
This changing will introduce:

1. When run 'rake clean', the object files of gem is not removed. To reduce the time when rebuild the project.
2. Across multiple projects that use the same gem, this changing will share the object files.
3. When update RubyMotion with 'motion update', it will remove the object files to clean up disk space.
2013-04-25 22:23:19 +09:00

284 lines
8.0 KiB
Ruby

#!/usr/bin/ruby
# Copyright (C) 2012, HipByte SPRL. All Rights Reserved.
#
# This file is subject to the terms and conditions of the End User License
# 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
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
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)