lib/bashly/library_source.rb
require 'fileutils'
require 'tmpdir'
module Bashly
class LibrarySource
attr_reader :uri
def initialize(uri = nil)
@uri = uri || File.expand_path('libraries', __dir__)
transform_github_uri if /^github(:|-)/.match? @uri
end
def git?
/^(git|github|github-ssh):/.match? uri
end
def config
@config ||= LibrarySourceConfig.new(config_path).validated_data
end
def libraries
config.to_h do |name, spec|
upgrade_string = "#{uri};#{name}"
[name.to_sym, Library.new(path, spec, upgrade_string: upgrade_string)]
end
end
def config_path
@config_path ||= if File.exist?("#{path}/libraries.yml")
"#{path}/libraries.yml"
else
raise "Cannot find #{path}/libraries.yml"
end
end
def cleanup
FileUtils.rm_rf(File.join(Dir.tmpdir, 'bashly-libs-*'))
end
private
def path
@path ||= if uri.start_with? 'git:'
git_clone
else
uri
end
end
def git_clone
dir = Dir.mktmpdir 'bashly-libs-'
safe_run "git clone --quiet #{git_specs[:url]} #{dir}"
safe_run %[git -C "#{dir}" checkout --quiet #{git_specs[:ref]}] if git_specs[:ref]
"#{dir}#{git_specs[:path]}"
end
def git_specs
@git_specs ||= begin
parts = uri.match(%r{git:(?<url>.*\.git)(?:/)?(?<path>/[^@]+)?@?(?<ref>.*)})
raise 'Invalid source' unless parts
url = parts[:url]
raise 'Invalid git URL' unless url
path = parts[:path]
ref = parts[:ref].empty? ? nil : parts[:ref]
{ url: url, path: path, ref: ref }
end
end
def safe_run(cmd)
raise "Failed running command:\nm`#{cmd}`" unless system cmd
end
def transform_github_uri
if (matches = uri.match(%r{github-ssh:(?<user>[^/]+)/(?<repo>[^/]+)(?<rest>.*)}))
@uri = "git:git@github.com:#{matches[:user]}/#{matches[:repo]}.git#{matches[:rest]}"
elsif (matches = uri.match(%r{github:(?<user>[^/]+)/(?<repo>[^/]+)(?<rest>.*)}))
@uri = "git:https://github.com/#{matches[:user]}/#{matches[:repo]}.git#{matches[:rest]}"
end
end
end
end