Files
build-emacs-for-macos/build.rb

207 lines
4.3 KiB
Ruby
Executable File

#!/usr/bin/env ruby
require 'json'
require 'date'
require 'optparse'
#
# Config
#
DOWNLOAD_URL = "https://github.com/emacsmirror/emacs/tarball/%s"
LATEST_URL = "https://api.github.com/repos/emacsmirror/emacs/commits?sha=%s"
ROOT_DIR = File.expand_path('..', __FILE__)
TARBALL_DIR = "#{ROOT_DIR}/tarballs"
SOURCES_DIR = "#{ROOT_DIR}/sources"
BUILDS_DIR = "#{ROOT_DIR}/builds"
#
# Main
#
def main
opts = parse_options
ref = ARGV.shift
meta = get_ref_info(ref)
if meta['sha'] && meta['date']
tarball = download_tarball(meta['sha'])
source = extract_tarball(tarball, patches(opts))
app = compile_source(source)
archive_app(app, meta['sha'], meta['date'])
else
raise "\nERROR: Failed to get commit info from GitHub API."
end
end
#
# Patches
#
def patches(opts = {})
p = []
if !opts[:no_fullscreen]
p << 'https://raw.github.com/gist/1012927'
end
if opts[:srgb]
p << 'https://raw.github.com/gist/1361934'
end
p
end
#
# Options
#
def parse_options
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: build.rb [options] [branch/sha]"
opts.on('--srgb', "Include sRGB patch.") do
options[:srgb] = true
end
opts.on("--no-fullscreen", "Don't include fullscreen patch") do
options[:no_fullscreen] = true
end
end.parse!
options
end
#
# Core Methods
#
def download_tarball(sha)
mkdir TARBALL_DIR
url = (DOWNLOAD_URL % sha)
filename = "emacsmirror-emacs-#{sha[0..6]}.tgz"
target = File.join(TARBALL_DIR, filename)
if !File.exist?(target)
puts "\nDownloading tarball from GitHub. This could take a while, " +
"please be patient."
system "curl -L \"#{url}\" -o \"#{target}\""
raise "\nERROR: Download failed." unless File.exist?(target)
else
puts "\nINFO: #{filename} already exists locally, attempting to use."
end
target
end
def extract_tarball(filename, patches = [])
mkdir SOURCES_DIR
dirname = File.basename(filename).gsub(/\.\w+$/, '')
target = "#{SOURCES_DIR}/#{dirname}"
if !File.exist?(target)
puts "\nExtracting tarball..."
system "tar -xzf \"#{filename}\" -C \"#{SOURCES_DIR}\""
raise "\nERROR: Tarball extraction failed." unless File.exist?(target)
patches.each do |url|
apply_patch(url, target)
end
else
puts "\nINFO: #{dirname} source tree exists, attempting to use."
end
target
end
def compile_source(source)
target = "#{source}/nextstep"
if !File.exist?("#{target}/Emacs.app")
puts "\nCompiling from source. This will take a while..."
if File.exist? "#{source}/autogen/copy_autogen"
system "cd \"#{source}\" && autogen/copy_autogen"
end
system "cd \"#{source}\" && ./configure --with-ns"
system "cd \"#{source}\" && make install"
raise "\nERROR: Build failed." unless File.exist?("#{target}/Emacs.app")
else
puts "\nINFO: Emacs.app already exists in " +
"\"#{target.gsub(ROOT_DIR + '/', '')}\", attempting to use."
end
"#{target}/Emacs.app"
end
def archive_app(app, sha, date)
mkdir BUILDS_DIR
filename = "Emacs.app-#{date}-(#{sha[0..6]}).tbz"
target = "#{BUILDS_DIR}/#{filename}"
app_base = File.basename(app)
app_dir = File.dirname(app)
if !File.exist?(target)
puts "\nCreating #{filename} archive in \"#{BUILDS_DIR}\"..."
system "cd \"#{app_dir}\" && tar -cjf \"#{target}\" \"#{app_base}\""
else
puts "\nINFO: #{filename} archive exists in " +
"#{BUILDS_DIR.gsub(ROOT_DIR + '/', '')}, skipping archving."
end
end
#
# Helper Methods
#
def mkdir(dir)
system "mkdir -p \"#{dir}\""
end
def get_ref_info(ref = 'master')
response = `curl "#{LATEST_URL % ref}" 2>/dev/null`
meta = JSON.parse(response).first
return {
'sha' => meta['sha'],
'date' => Date.parse(meta['commit']['committer']['date'])
}
end
def apply_patch(url, target)
raise "ERROR: \"#{target}\" does not exist." unless File.exist?(target)
system "mkdir -p \"#{target}/patches\""
patch_file = "#{target}/patches/patch-{num}.diff"
num = 1
while File.exist? patch_file.gsub('{num}', num.to_s.rjust(3, '0'))
num += 1
end
patch_file.gsub!('{num}', num.to_s.rjust(3, '0'))
puts "Downloading patch: #{url}"
system "curl -L# \"#{url}\" -o \"#{patch_file}\""
puts "Applying patch..."
system "cd \"#{target}\" && patch -f -p1 -i \"#{patch_file}\""
end
#
# Run it!
#
main