lib/librarian/puppet/source/githubtarball.rb in librarian-puppet-1.0.1 vs lib/librarian/puppet/source/githubtarball.rb in librarian-puppet-1.0.2

- old
+ new

@@ -1,170 +1,15 @@ require 'uri' -require 'net/https' -require 'open-uri' -require 'json' +require 'librarian/puppet/util' +require 'librarian/puppet/source/githubtarball/repo' -require 'librarian/puppet/version' - module Librarian module Puppet module Source class GitHubTarball include Librarian::Puppet::Util - class Repo - include Librarian::Puppet::Util - - TOKEN_KEY = 'GITHUB_API_TOKEN' - - attr_accessor :source, :name - private :source=, :name= - - def initialize(source, name) - self.source = source - self.name = name - end - - def versions - return @versions if @versions - data = api_call("/repos/#{source.uri}/tags") - if data.nil? - raise Error, "Unable to find module '#{source.uri}' on https://github.com" - end - - all_versions = data.map { |r| r['name'].gsub(/^v/, '') }.sort.reverse - - all_versions.delete_if do |version| - version !~ /\A\d\.\d(\.\d.*)?\z/ - end - - @versions = all_versions.compact - debug { " Module #{name} found versions: #{@versions.join(", ")}" } - @versions - end - - def manifests - versions.map do |version| - Manifest.new(source, name, version) - end - end - - def install_version!(version, install_path) - if environment.local? && !vendored?(source.uri, version) - raise Error, "Could not find a local copy of #{source.uri} at #{version}." - end - - vendor_cache(source.uri, version) unless vendored?(source.uri, version) - - cache_version_unpacked! version - - if install_path.exist? - install_path.rmtree - end - - unpacked_path = version_unpacked_cache_path(version).children.first - cp_r(unpacked_path, install_path) - end - - def environment - source.environment - end - - def cache_path - @cache_path ||= source.cache_path.join(name) - end - - def version_unpacked_cache_path(version) - cache_path.join('version').join(hexdigest(version.to_s)) - end - - def hexdigest(value) - Digest::MD5.hexdigest(value) - end - - def cache_version_unpacked!(version) - path = version_unpacked_cache_path(version) - return if path.directory? - - path.mkpath - - target = vendored?(source.uri, version) ? vendored_path(source.uri, version) : name - - Librarian::Posix.run!(%W{tar xzf #{target} -C #{path}}) - end - - def vendored?(name, version) - vendored_path(name, version).exist? - end - - def vendored_path(name, version) - environment.vendor_cache.mkpath - environment.vendor_cache.join("#{name.sub("/", "-")}-#{version}.tar.gz") - end - - def vendor_cache(name, version) - clean_up_old_cached_versions(name) - - url = "https://api.github.com/repos/#{name}/tarball/#{version}" - url << "?access_token=#{ENV['GITHUB_API_TOKEN']}" if ENV['GITHUB_API_TOKEN'] - - File.open(vendored_path(name, version).to_s, 'wb') do |f| - begin - debug { "Downloading <#{url}> to <#{f.path}>" } - open(url, - "User-Agent" => "librarian-puppet v#{Librarian::Puppet::VERSION}") do |res| - while buffer = res.read(8192) - f.write(buffer) - end - end - rescue OpenURI::HTTPError => e - raise e, "Error requesting <#{url}>: #{e.to_s}" - end - end - end - - def clean_up_old_cached_versions(name) - Dir["#{environment.vendor_cache}/#{name.sub('/', '-')}*.tar.gz"].each do |old_version| - FileUtils.rm old_version - end - end - - private - - def api_call(path) - url = "https://api.github.com#{path}" - url << "?access_token=#{ENV[TOKEN_KEY]}" if ENV[TOKEN_KEY] - code, data = http_get(url, :headers => { - "User-Agent" => "librarian-puppet v#{Librarian::Puppet::VERSION}" - }) - - if code == 200 - JSON.parse(data) - elsif code == 403 - begin - message = JSON.parse(data)['message'] - if message && message.include?('API rate limit exceeded') - raise Error, message + " -- increase limit by authenticating via #{TOKEN_KEY}=your-token" - end - rescue JSON::ParserError - # 403 response does not return json, skip. - end - end - end - - def http_get(url, options) - uri = URI.parse(url) - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - request = Net::HTTP::Get.new(uri.request_uri) - options[:headers].each { |k, v| request.add_field k, v } - resp = http.request(request) - [resp.code.to_i, resp.body] - end - end - class << self LOCK_NAME = 'GITHUBTARBALL' def lock_name LOCK_NAME @@ -189,16 +34,16 @@ private :environment= attr_reader :uri def initialize(environment, uri, options = {}) self.environment = environment - @uri = uri + @uri = URI::parse(uri) @cache_path = nil end def to_s - uri + clean_uri(uri).to_s end def ==(other) other && self.class == other.class && @@ -210,15 +55,15 @@ def hash self.to_s.hash end def to_spec_args - [uri, {}] + [clean_uri(uri).to_s, {}] end def to_lock_options - {:remote => uri} + {:remote => clean_uri(uri).to_s} end def pinned? false end @@ -227,10 +72,12 @@ end def install!(manifest) manifest.source == self or raise ArgumentError + debug { "Installing #{manifest}" } + name = manifest.name version = manifest.version install_path = install_path(name) repo = repo(name) @@ -244,11 +91,10 @@ manifest end def cache_path @cache_path ||= begin - dir = Digest::MD5.hexdigest(uri) - environment.cache_path.join("source/puppet/githubtarball/#{dir}") + environment.cache_path.join("source/puppet/githubtarball/#{uri.host}#{uri.path}") end end def install_path(name) environment.install_path.join(name.split('/').last)