mirror of
https://github.com/jimeh/build-emacs-for-macos.git
synced 2026-02-19 13:06:38 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
8d165b627b
|
|||
|
9c977a75b5
|
21
CHANGELOG.md
21
CHANGELOG.md
@@ -2,27 +2,6 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
### [0.4.12](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.11...0.4.12) (2021-05-17)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **shared-libraries:** stop aggressive dylib re-linking ([0a22d83](https://github.com/jimeh/build-emacs-for-macos/commit/0a22d8393c53305354c4c6d8e784e7d59caa039a)), closes [#12](https://github.com/jimeh/build-emacs-for-macos/issues/12)
|
|
||||||
* **svg:** enable SVG by default via librsvg ([bf7c4d5](https://github.com/jimeh/build-emacs-for-macos/commit/bf7c4d5debf32980dbbabc1ea99b58b266390011))
|
|
||||||
|
|
||||||
### [0.4.11](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.10...0.4.11) (2021-05-08)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **builds:** update build script for new plan.yml format ([1df39fa](https://github.com/jimeh/build-emacs-for-macos/commit/1df39fafe62ada385aa1d92e6b7f591c16c0a80c))
|
|
||||||
* **release:** initial attempt at providing automatic builds ([6328921](https://github.com/jimeh/build-emacs-for-macos/commit/63289216d70e496d664a7e3078dea5a82eb8f65d))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **release:** attempt to fix issue with talking to GitHub API ([272a300](https://github.com/jimeh/build-emacs-for-macos/commit/272a3000a1f96d8f131e684736127b923513a205))
|
|
||||||
|
|
||||||
### [0.4.10](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.9...0.4.10) (2021-04-25)
|
### [0.4.10](https://github.com/jimeh/build-emacs-for-macos/compare/0.4.9...0.4.10) (2021-04-25)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
52
bin/commit-info
Executable file
52
bin/commit-info
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
require_relative '../lib/commit_info'
|
||||||
|
require_relative '../lib/errors'
|
||||||
|
require_relative '../lib/log'
|
||||||
|
|
||||||
|
options = {
|
||||||
|
repo: 'emacs-mirror/emacs',
|
||||||
|
output: File.expand_path('../tarballs', __dir__),
|
||||||
|
log_level: :info
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionParser.new do |opts|
|
||||||
|
opts.banner = <<~TXT
|
||||||
|
Usage: ./commit-info [options] <branch/tag/sha>
|
||||||
|
|
||||||
|
Fetch commit info of given GitHub repository branch, tag, or SHA.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
TXT
|
||||||
|
|
||||||
|
opts.on('-r', '--repo STRING',
|
||||||
|
"GitHub repository (default: #{options[:repo]})") do |v|
|
||||||
|
options[:repo] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on('-o', '--output DIR', 'Directory to save tarball in ' \
|
||||||
|
"(default: #{options[:output]})") do |v|
|
||||||
|
options[:output] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on('-l', '--log-level LEVEL', 'Log level ' \
|
||||||
|
"(default: #{options[:log_level]})") do |v|
|
||||||
|
options[:log_level] = v.to_sym
|
||||||
|
end
|
||||||
|
end.parse!
|
||||||
|
|
||||||
|
begin
|
||||||
|
logger = Log.new('commit-info', options[:log_level])
|
||||||
|
commit = CommitInfo.new(
|
||||||
|
ref: ARGV[0],
|
||||||
|
repo: options[:repo],
|
||||||
|
logger: logger
|
||||||
|
).perform
|
||||||
|
|
||||||
|
puts commit.to_yaml
|
||||||
|
rescue Error => e
|
||||||
|
handle_error(e)
|
||||||
|
end
|
||||||
53
bin/download-tarball
Executable file
53
bin/download-tarball
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
require_relative '../lib/download_tarball'
|
||||||
|
require_relative '../lib/errors'
|
||||||
|
require_relative '../lib/log'
|
||||||
|
|
||||||
|
options = {
|
||||||
|
repo: 'emacs-mirror/emacs',
|
||||||
|
output: File.expand_path('../tarballs', __dir__),
|
||||||
|
log_level: :info
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionParser.new do |opts|
|
||||||
|
opts.banner = <<~TXT
|
||||||
|
Usage: ./download-tarball [options] <branch/tag/sha>
|
||||||
|
|
||||||
|
Download a tarball of given GitHub repository branch, tag, or SHA.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
TXT
|
||||||
|
|
||||||
|
opts.on('-r', '--repo STRING',
|
||||||
|
"GitHub repository (default: #{options[:repo]})") do |v|
|
||||||
|
options[:repo] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on('-o', '--output DIR', 'Directory to save tarball in ' \
|
||||||
|
"(default: #{options[:output]})") do |v|
|
||||||
|
options[:output] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on('-l', '--log-level LEVEL', 'Log level ' \
|
||||||
|
"(default: #{options[:log_level]})") do |v|
|
||||||
|
options[:log_level] = v.to_sym
|
||||||
|
end
|
||||||
|
end.parse!
|
||||||
|
|
||||||
|
begin
|
||||||
|
logger = Log.new('download-tarball', options[:log_level])
|
||||||
|
tarball = DownloadTarball.new(
|
||||||
|
ref: ARGV[0],
|
||||||
|
repo: options[:repo],
|
||||||
|
output: options[:output],
|
||||||
|
logger: logger
|
||||||
|
).perform
|
||||||
|
|
||||||
|
puts tarball.to_yaml
|
||||||
|
rescue Error => e
|
||||||
|
handle_error(e)
|
||||||
|
end
|
||||||
@@ -10,9 +10,7 @@ require 'json'
|
|||||||
require 'net/http'
|
require 'net/http'
|
||||||
require 'optparse'
|
require 'optparse'
|
||||||
require 'pathname'
|
require 'pathname'
|
||||||
require 'time'
|
|
||||||
require 'uri'
|
require 'uri'
|
||||||
require 'yaml'
|
|
||||||
|
|
||||||
class Error < StandardError; end
|
class Error < StandardError; end
|
||||||
|
|
||||||
@@ -23,9 +21,9 @@ module Output
|
|||||||
|
|
||||||
def out(msg, newline: true)
|
def out(msg, newline: true)
|
||||||
if newline
|
if newline
|
||||||
warn "==> #{msg}"
|
puts "==> #{msg}"
|
||||||
else
|
else
|
||||||
STDERR.print "==> #{msg}"
|
print "==> #{msg}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -89,10 +87,8 @@ class Build
|
|||||||
end
|
end
|
||||||
|
|
||||||
def build
|
def build
|
||||||
load_plan(options[:plan]) if options[:plan]
|
|
||||||
|
|
||||||
unless meta[:sha] && meta[:date]
|
unless meta[:sha] && meta[:date]
|
||||||
err 'Failed to get commit info from GitHub.'
|
err 'Failed to get commit info from GitHub API.'
|
||||||
end
|
end
|
||||||
|
|
||||||
tarball = download_tarball(meta[:sha])
|
tarball = download_tarball(meta[:sha])
|
||||||
@@ -112,17 +108,6 @@ class Build
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_plan(filename)
|
|
||||||
plan = YAML.safe_load(File.read(filename), [:Time])
|
|
||||||
|
|
||||||
@meta = {
|
|
||||||
sha: plan.dig('commit', 'sha'),
|
|
||||||
ref: plan.dig('commit', 'ref'),
|
|
||||||
date: plan.dig('commit', 'date')
|
|
||||||
}
|
|
||||||
@archive_filename = plan['archive']
|
|
||||||
end
|
|
||||||
|
|
||||||
def tarballs_dir
|
def tarballs_dir
|
||||||
@tarballs_dir ||= File.join(root_dir, 'tarballs')
|
@tarballs_dir ||= File.join(root_dir, 'tarballs')
|
||||||
end
|
end
|
||||||
@@ -314,7 +299,7 @@ class Build
|
|||||||
configure_flags << '--with-xwidgets'
|
configure_flags << '--with-xwidgets'
|
||||||
end
|
end
|
||||||
configure_flags << native_comp_configure_flag if options[:native_comp]
|
configure_flags << native_comp_configure_flag if options[:native_comp]
|
||||||
configure_flags << '--without-rsvg' if options[:rsvg] == false
|
configure_flags << '--without-rsvg' unless options[:rsvg]
|
||||||
|
|
||||||
run_cmd './configure', *configure_flags
|
run_cmd './configure', *configure_flags
|
||||||
|
|
||||||
@@ -373,39 +358,29 @@ class Build
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def archive_filename
|
def archive_app(app)
|
||||||
return @archive_filename if @archive_filename
|
FileUtils.mkdir_p(builds_dir)
|
||||||
|
|
||||||
metadata = [
|
metadata = [
|
||||||
meta[:ref]&.gsub(/\W/, '-'),
|
meta[:ref]&.gsub(/\W/, '-'),
|
||||||
meta[:date]&.strftime('%Y-%m-%d'),
|
meta[:date],
|
||||||
meta[:sha][0..6],
|
meta[:sha][0..6],
|
||||||
"macOS-#{OS.version}",
|
"macOS-#{OS.version}",
|
||||||
OS.arch
|
OS.arch
|
||||||
].compact
|
].compact
|
||||||
|
|
||||||
filename = "Emacs.app-[#{metadata.join('][')}].tbz"
|
filename = "Emacs.app-[#{metadata.join('][')}].tbz"
|
||||||
@archive_filename = File.join(builds_dir, filename)
|
target = "#{builds_dir}/#{filename}"
|
||||||
end
|
|
||||||
|
|
||||||
def archive_app(app)
|
|
||||||
filename = File.basename(archive_filename)
|
|
||||||
target_dir = File.dirname(archive_filename)
|
|
||||||
relative_target_dir = target_dir.gsub(root_dir + '/', '')
|
|
||||||
|
|
||||||
FileUtils.mkdir_p(target_dir)
|
|
||||||
|
|
||||||
app_base = File.basename(app)
|
app_base = File.basename(app)
|
||||||
app_dir = File.dirname(app)
|
app_dir = File.dirname(app)
|
||||||
|
|
||||||
if !File.exist?(archive_filename)
|
if !File.exist?(target)
|
||||||
info "Creating #{filename} archive in \"#{relative_target_dir}\"..."
|
info "Creating #{filename} archive in \"#{builds_dir}\"..."
|
||||||
FileUtils.cd(app_dir) do
|
FileUtils.cd(app_dir) { system('tar', '-cjf', target, app_base) }
|
||||||
system('tar', '-cjf', archive_filename, app_base)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
info "#{filename} archive exists in " \
|
info "#{filename} archive exists in " \
|
||||||
"#{relative_target_dir}, skipping archving."
|
"#{builds_dir.gsub(root_dir + '/', '')}, skipping archving."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -436,7 +411,7 @@ class Build
|
|||||||
commit = JSON.parse(commit_json)
|
commit = JSON.parse(commit_json)
|
||||||
meta = {
|
meta = {
|
||||||
sha: commit['sha'],
|
sha: commit['sha'],
|
||||||
date: Time.parse(commit['commit']['committer']['date'])
|
date: Date.parse(commit['commit']['committer']['date'])
|
||||||
}
|
}
|
||||||
meta[:ref] = ref if ref && ref[0..6] != meta[:sha][0..6]
|
meta[:ref] = ref if ref && ref[0..6] != meta[:sha][0..6]
|
||||||
|
|
||||||
@@ -617,6 +592,7 @@ class LibEmbedder < AbstractEmbedder
|
|||||||
FileUtils.cd(File.dirname(app)) do
|
FileUtils.cd(File.dirname(app)) do
|
||||||
copy_libs(binary)
|
copy_libs(binary)
|
||||||
copy_extra_libs(extra_libs, binary) if extra_libs.any?
|
copy_extra_libs(extra_libs, binary) if extra_libs.any?
|
||||||
|
self_ref_libs(binary)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -628,11 +604,6 @@ class LibEmbedder < AbstractEmbedder
|
|||||||
Pathname.new(File.dirname(exe))
|
Pathname.new(File.dirname(exe))
|
||||||
).to_s
|
).to_s
|
||||||
|
|
||||||
while_writable(exe) do
|
|
||||||
system('install_name_tool', '-add_rpath',
|
|
||||||
File.join('@executable_path', rel_path), exe)
|
|
||||||
end
|
|
||||||
|
|
||||||
`otool -L "#{exe}"`.split("\n")[1..-1].each do |line|
|
`otool -L "#{exe}"`.split("\n")[1..-1].each do |line|
|
||||||
match = line.match(%r{^\s+(.+/(lib[^/ ]+))\s})
|
match = line.match(%r{^\s+(.+/(lib[^/ ]+))\s})
|
||||||
next unless match && match[1].start_with?(lib_source)
|
next unless match && match[1].start_with?(lib_source)
|
||||||
@@ -677,6 +648,31 @@ class LibEmbedder < AbstractEmbedder
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self_ref_libs(exe)
|
||||||
|
rel_path = Pathname.new(lib_dir).relative_path_from(
|
||||||
|
Pathname.new(File.dirname(exe))
|
||||||
|
).to_s
|
||||||
|
lib_paths ||= Dir.glob("#{lib_dir}/*").select { |f| File.file?(f) }
|
||||||
|
libs = lib_paths.map { |f| File.basename(f) }
|
||||||
|
|
||||||
|
([exe] + lib_paths).each do |bin_path|
|
||||||
|
`otool -L "#{bin_path}"`.split("\n")[1..-1].each do |line|
|
||||||
|
match = line.match(%r{^\s+(.+/(lib[^/ ]+))\s})
|
||||||
|
next unless match
|
||||||
|
next if match[1].start_with?('@executable_path/')
|
||||||
|
next unless libs.include?(match[2])
|
||||||
|
|
||||||
|
while_writable(bin_path) do
|
||||||
|
system(
|
||||||
|
'install_name_tool', '-change', match[1],
|
||||||
|
File.join('@executable_path', rel_path, match[2].to_s),
|
||||||
|
bin_path
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def while_writable(file)
|
def while_writable(file)
|
||||||
mode = File.stat(file).mode
|
mode = File.stat(file).mode
|
||||||
File.chmod(0o775, file)
|
File.chmod(0o775, file)
|
||||||
@@ -816,10 +812,9 @@ end
|
|||||||
|
|
||||||
if __FILE__ == $PROGRAM_NAME
|
if __FILE__ == $PROGRAM_NAME
|
||||||
cli_options = {
|
cli_options = {
|
||||||
work_dir: File.expand_path(__dir__),
|
|
||||||
native_full_aot: false,
|
native_full_aot: false,
|
||||||
parallel: Etc.nprocessors,
|
parallel: Etc.nprocessors,
|
||||||
rsvg: true,
|
rsvg: false,
|
||||||
xwidgets: true
|
xwidgets: true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,19 +831,18 @@ if __FILE__ == $PROGRAM_NAME
|
|||||||
|
|
||||||
opts.on('-j', '--parallel COUNT',
|
opts.on('-j', '--parallel COUNT',
|
||||||
'Compile using COUNT parallel processes ' \
|
'Compile using COUNT parallel processes ' \
|
||||||
"(default: #{cli_options[:parallel]})") do |v|
|
"(detected: #{cli_options[:parallel]})") do |v|
|
||||||
cli_options[:parallel] = v
|
cli_options[:parallel] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--git-sha SHA',
|
opts.on('--git-sha SHA', 'Override detected git SHA of specified ' \
|
||||||
'Override detected git SHA of specified ' \
|
'branch allowing builds of old commits') do |v|
|
||||||
'branch allowing builds of old commits') do |v|
|
|
||||||
cli_options[:git_sha] = v
|
cli_options[:git_sha] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--[no-]xwidgets',
|
opts.on('--[no-]xwidgets',
|
||||||
'Enable/disable XWidgets if supported ' \
|
'Enable/disable XWidgets ' \
|
||||||
'(default: enabled)') do |v|
|
'(default: enabled if supported)') do |v|
|
||||||
cli_options[:xwidgets] = v
|
cli_options[:xwidgets] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -864,10 +858,9 @@ if __FILE__ == $PROGRAM_NAME
|
|||||||
cli_options[:native_full_aot] = v
|
cli_options[:native_full_aot] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--[no-]rsvg',
|
opts.on('--rsvg', 'Enable SVG image support via librsvg, ' \
|
||||||
'Enable/disable SVG image support via librsvg ' \
|
'can yield a unstable build (default: disabled)') do
|
||||||
'(default: enabled)') do |v|
|
cli_options[:rsvg] = true
|
||||||
cli_options[:rsvg] = v
|
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--no-titlebar', 'Apply no-titlebar patch (default: disabled)') do
|
opts.on('--no-titlebar', 'Apply no-titlebar patch (default: disabled)') do
|
||||||
@@ -879,19 +872,6 @@ if __FILE__ == $PROGRAM_NAME
|
|||||||
cli_options[:no_frame_refocus] = true
|
cli_options[:no_frame_refocus] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--work-dir DIR',
|
|
||||||
'Specify a working directory where tarballs, sources, and ' \
|
|
||||||
'builds will be stored and worked with') do |v|
|
|
||||||
cli_options[:work_dir] = v
|
|
||||||
end
|
|
||||||
|
|
||||||
opts.on(
|
|
||||||
'--plan FILE',
|
|
||||||
'Follow given plan file, instead of using given git ref/sha'
|
|
||||||
) do |v|
|
|
||||||
cli_options[:plan] = v
|
|
||||||
end
|
|
||||||
|
|
||||||
opts.on('--[no-]native-fast-boot',
|
opts.on('--[no-]native-fast-boot',
|
||||||
'DEPRECATED: use --[no-]native-full-aot instead') do |v|
|
'DEPRECATED: use --[no-]native-full-aot instead') do |v|
|
||||||
if v
|
if v
|
||||||
@@ -910,8 +890,7 @@ if __FILE__ == $PROGRAM_NAME
|
|||||||
end
|
end
|
||||||
end.parse!
|
end.parse!
|
||||||
|
|
||||||
work_dir = cli_options.delete(:work_dir)
|
Build.new(File.expand_path(__dir__), ARGV.shift, cli_options).build
|
||||||
Build.new(work_dir, ARGV.shift, cli_options).build
|
|
||||||
rescue Error => e
|
rescue Error => e
|
||||||
warn "ERROR: #{e.message}"
|
warn "ERROR: #{e.message}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
9
lib/base_action.rb
Normal file
9
lib/base_action.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative './common'
|
||||||
|
require_relative './output'
|
||||||
|
|
||||||
|
class BaseAction
|
||||||
|
include Common
|
||||||
|
include Output
|
||||||
|
end
|
||||||
46
lib/commit.rb
Normal file
46
lib/commit.rb
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require 'time'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
require_relative './errors'
|
||||||
|
require_relative './common'
|
||||||
|
|
||||||
|
class Commit
|
||||||
|
include Common
|
||||||
|
|
||||||
|
attr_reader :repo
|
||||||
|
attr_reader :ref
|
||||||
|
attr_reader :message
|
||||||
|
attr_reader :sha
|
||||||
|
attr_reader :time
|
||||||
|
|
||||||
|
def initialize(sha:, time:, repo: nil, ref: nil, message: nil)
|
||||||
|
@sha = sha
|
||||||
|
@time = time
|
||||||
|
@repo = repo
|
||||||
|
@ref = ref
|
||||||
|
@message = message
|
||||||
|
end
|
||||||
|
|
||||||
|
def sha_short
|
||||||
|
sha[0..6]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash
|
||||||
|
{
|
||||||
|
'repo' => repo,
|
||||||
|
'ref' => ref,
|
||||||
|
'sha' => sha,
|
||||||
|
'sha_short' => sha_short,
|
||||||
|
'time' => time.utc,
|
||||||
|
'timestamp' => time.utc.to_i,
|
||||||
|
'message' => message
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_yaml
|
||||||
|
to_hash.to_yaml
|
||||||
|
end
|
||||||
|
end
|
||||||
43
lib/commit_info.rb
Normal file
43
lib/commit_info.rb
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative './base_action'
|
||||||
|
require_relative './commit'
|
||||||
|
|
||||||
|
class CommitInfo < BaseAction
|
||||||
|
COMMIT_URL = 'https://api.github.com/repos/%s/commits/%s'
|
||||||
|
|
||||||
|
attr_reader :ref
|
||||||
|
attr_reader :repo
|
||||||
|
attr_reader :logger
|
||||||
|
|
||||||
|
def initialize(ref:, repo:, logger:)
|
||||||
|
@ref = ref
|
||||||
|
@repo = repo
|
||||||
|
@logger = logger
|
||||||
|
|
||||||
|
err 'branch/tag/sha argument cannot be empty' if ref.nil? || ref.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
info "Fetching info for git ref: #{ref}"
|
||||||
|
|
||||||
|
url = format(COMMIT_URL, repo, ref)
|
||||||
|
commit_json = http_get(url)
|
||||||
|
|
||||||
|
err "Failed to get commit info about: #{ref}" if commit_json.nil?
|
||||||
|
|
||||||
|
parsed = JSON.parse(commit_json)
|
||||||
|
commit = Commit.new(
|
||||||
|
repo: repo,
|
||||||
|
ref: ref,
|
||||||
|
sha: parsed&.dig('sha'),
|
||||||
|
message: parsed&.dig('commit', 'message'),
|
||||||
|
time: Time.parse(parsed&.dig('commit', 'committer', 'date')).utc
|
||||||
|
)
|
||||||
|
|
||||||
|
err 'Failed to get commit SHA' if commit.sha.nil? || commit.sha.empty?
|
||||||
|
err 'Failed to get commit time' if commit.time.nil?
|
||||||
|
|
||||||
|
commit
|
||||||
|
end
|
||||||
|
end
|
||||||
23
lib/common.rb
Normal file
23
lib/common.rb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'net/http'
|
||||||
|
|
||||||
|
module Common
|
||||||
|
private
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
base.extend(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_cmd(*args)
|
||||||
|
info "executing: #{args.join(' ')}"
|
||||||
|
system(*args) || err("Exit code: #{$CHILD_STATUS.exitstatus}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def http_get(url)
|
||||||
|
response = Net::HTTP.get_response(URI.parse(url))
|
||||||
|
return unless response.code == '200'
|
||||||
|
|
||||||
|
response.body
|
||||||
|
end
|
||||||
|
end
|
||||||
61
lib/download_tarball.rb
Normal file
61
lib/download_tarball.rb
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'fileutils'
|
||||||
|
require 'json'
|
||||||
|
require 'time'
|
||||||
|
|
||||||
|
require_relative './base_action'
|
||||||
|
|
||||||
|
require_relative './commit_info'
|
||||||
|
require_relative './tarball'
|
||||||
|
|
||||||
|
class DownloadTarball < BaseAction
|
||||||
|
TARBALL_URL = 'https://github.com/%s/tarball/%s'
|
||||||
|
|
||||||
|
attr_reader :ref
|
||||||
|
attr_reader :repo
|
||||||
|
attr_reader :output
|
||||||
|
attr_reader :logger
|
||||||
|
|
||||||
|
def initialize(ref:, repo:, output:, logger:)
|
||||||
|
@ref = ref
|
||||||
|
@repo = repo
|
||||||
|
@output = output
|
||||||
|
@logger = logger
|
||||||
|
|
||||||
|
err 'branch/tag/sha argument cannot be empty' if ref.nil? || ref.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
FileUtils.mkdir_p(output)
|
||||||
|
tarball = Tarball.new(file: target, commit: commit)
|
||||||
|
|
||||||
|
if File.exist?(target)
|
||||||
|
info "#{filename} already exists locally, attempting to use."
|
||||||
|
return tarball
|
||||||
|
end
|
||||||
|
|
||||||
|
info 'Downloading tarball from GitHub. This could take a while, ' \
|
||||||
|
'please be patient.'
|
||||||
|
result = run_cmd('curl', '-L', url, '-o', target)
|
||||||
|
err 'Download failed.' if !result || !File.exist?(target)
|
||||||
|
|
||||||
|
tarball
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
@url ||= format(TARBALL_URL, repo, commit.sha)
|
||||||
|
end
|
||||||
|
|
||||||
|
def filename
|
||||||
|
@filename ||= "#{repo.gsub(/[^\w]/, '-')}-#{commit.sha_short}.tgz"
|
||||||
|
end
|
||||||
|
|
||||||
|
def target
|
||||||
|
@target ||= File.join(output, filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit
|
||||||
|
@commit ||= CommitInfo.new(ref: ref, repo: repo, logger: logger).perform
|
||||||
|
end
|
||||||
|
end
|
||||||
12
lib/errors.rb
Normal file
12
lib/errors.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
def handle_error(err)
|
||||||
|
warn "ERROR: #{err.message}"
|
||||||
|
Process.exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
class Error < StandardError; end
|
||||||
|
|
||||||
|
class CommitNotFound < Error; end
|
||||||
|
class NoCommitSHA < Error; end
|
||||||
|
class NoCommitTime < Error; end
|
||||||
31
lib/log.rb
Normal file
31
lib/log.rb
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Log
|
||||||
|
extend Forwardable
|
||||||
|
|
||||||
|
attr_reader :name
|
||||||
|
attr_reader :level
|
||||||
|
|
||||||
|
def initialize(name, level = :info)
|
||||||
|
@name = name
|
||||||
|
@level = level
|
||||||
|
end
|
||||||
|
|
||||||
|
def_delegators :logger, :debug, :info, :warn, :error, :fatal, :unkonwn
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def logger
|
||||||
|
@logger ||= Logger.new($stderr).tap do |l|
|
||||||
|
l.progname = name
|
||||||
|
l.level = level
|
||||||
|
l.formatter = formatter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def formatter
|
||||||
|
proc do |severity, _datetime, progname, msg|
|
||||||
|
"==> [#{progname}] #{severity}: #{msg}\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
28
lib/output.rb
Normal file
28
lib/output.rb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'forwardable'
|
||||||
|
require 'logger'
|
||||||
|
|
||||||
|
require_relative './errors'
|
||||||
|
|
||||||
|
module Output
|
||||||
|
extend Forwardable
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
base.extend(ClassMethods)
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
def logger_name(name = nil)
|
||||||
|
return @logger_name if name.nil?
|
||||||
|
|
||||||
|
@logger_name = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def_delegators :logger, :debug, :info, :warn, :error, :fatal, :unkonwn
|
||||||
|
|
||||||
|
def err(msg = nil)
|
||||||
|
raise Error, msg
|
||||||
|
end
|
||||||
|
end
|
||||||
24
lib/tarball.rb
Normal file
24
lib/tarball.rb
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
class Tarball
|
||||||
|
attr_reader :file
|
||||||
|
attr_reader :commit
|
||||||
|
|
||||||
|
def initialize(file:, commit:)
|
||||||
|
@file = file
|
||||||
|
@commit = commit
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash
|
||||||
|
{
|
||||||
|
'file' => file,
|
||||||
|
'commit' => commit.to_hash
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_yaml
|
||||||
|
to_hash.to_yaml
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user