Доморощенный - Пользовательская стратегия загрузки не работает - PullRequest
1 голос
/ 10 июня 2019

Я пытаюсь создать собственную стратегию загрузки в доморощенном стиле, но тап не работает.

Ошибка ниже отображается после того, как я попытался выполнить команду brew tap ericofusco / test

Я следовал инструкциям от: http://lessthanhero.io/post/homebrew-with-private-repo-releases/.

Кажется, он ожидает, что у меня есть имя класса с именем моего имени файла.

Error: Invalid formula: /usr/local/Homebrew/Library/Taps/ericofusco/homebrew-test/custom_download_strategy.rb
No available formula with the name "custom_download_strategy"
In formula file: /usr/local/Homebrew/Library/Taps/ericofusco/homebrew-test/custom_download_strategy.rb
Expected to find class CustomDownloadStrategy, but only found: CustomGitHubPrivateRepositoryDownloadStrategy, CustomGitHubPrivateRepositoryReleaseDownloadStrategy (not derived from Formula!).
Error: Cannot tap ericofusco/test: invalid syntax in tap!

formula.rb

require_relative "../custom_download_strategy"

class Test < Formula
  desc ""
  homepage "https://github.com/ericofusco/test"
  url "https://github.com/ericofusco/test/releases/download/v1.0.0/test_1.0.0_darwin_amd64.tar.gz", :using => CustomGitHubPrivateRepositoryReleaseDownloadStrategy
  version "1.0.0"
  sha256 "2436b4c63020b343f0b667c2f6797681c71d2598fa600691b7fd9593fd9ca7ee"

  def install
    bin.install "test"
  end
end

custom_download_strategy.rb

require "download_strategy"

# GitHubPrivateRepositoryDownloadStrategy downloads contents from GitHub
# Private Repository. To use it, add
# `:using => :github_private_repo` to the URL section of
# your formula. This download strategy uses GitHub access tokens (in the
# environment variables `HOMEBREW_GITHUB_API_TOKEN`) to sign the request.  This
# strategy is suitable for corporate use just like S3DownloadStrategy, because
# it lets you use a private GitHub repository for internal distribution.  It
# works with public one, but in that case simply use CurlDownloadStrategy.
class CustomGitHubPrivateRepositoryDownloadStrategy < CurlDownloadStrategy
  require "utils/formatter"
  require "utils/github"

  def initialize(url, name, version, **meta)
    super
    parse_url_pattern
    set_github_token
  end

  def parse_url_pattern
    unless match = url.match(%r{https://github.com/([^/]+)/([^/]+)/(\S+)})
      raise CurlDownloadStrategyError, "Invalid url pattern for GitHub Repository."
    end

    _, @owner, @repo, @filepath = *match
  end

  def download_url
    "https://github.com/#{@owner}/#{@repo}/#{@filepath}"
  end

  private

  def _fetch(url:, resolved_url:)
    curl_download download_url, "--header", "Authorization: token #{@github_token}", to: temporary_path
  end

  def set_github_token
    @github_token = ENV["HOMEBREW_GITHUB_API_TOKEN"]
    unless @github_token
      raise CurlDownloadStrategyError, "Environmental variable HOMEBREW_GITHUB_API_TOKEN is required."
    end

    validate_github_repository_access!
  end

  def validate_github_repository_access!
    # Test access to the repository
    GitHub.repository(@owner, @repo)
  rescue GitHub::HTTPNotFoundError
    # We only handle HTTPNotFoundError here,
    # becase AuthenticationFailedError is handled within util/github.
    message = <<~EOS
      HOMEBREW_GITHUB_API_TOKEN can not access the repository: #{@owner}/#{@repo}
      This token may not have permission to access the repository or the url of formula may be incorrect.
    EOS
    raise CurlDownloadStrategyError, message
  end
end

# GitHubPrivateRepositoryReleaseDownloadStrategy downloads tarballs from GitHub
# Release assets. To use it, add `:using => :github_private_release` to the URL section
# of your formula. This download strategy uses GitHub access tokens (in the
# environment variables HOMEBREW_GITHUB_API_TOKEN) to sign the request.
class CustomGitHubPrivateRepositoryReleaseDownloadStrategy < CustomGitHubPrivateRepositoryDownloadStrategy
  require 'net/http'

  def initialize(url, name, version, **meta)
    super
  end

  def parse_url_pattern
    url_pattern = %r{https://github.com/([^/]+)/([^/]+)/releases/download/([^/]+)/(\S+)}
    unless @url =~ url_pattern
      raise CurlDownloadStrategyError, "Invalid url pattern for GitHub Release."
    end

    _, @owner, @repo, @tag, @filename = *@url.match(url_pattern)
  end

  def download_url
    #"https://#{@github_token}@api.github.com/repos/#{@owner}/#{@repo}/releases/assets/#{asset_id}"
    #blah = curl_output "--header", "Accept: application/octet-stream", "--header", "Authorization: token #{@github_token}", "-I"
    uri = URI("https://api.github.com/repos/#{@owner}/#{@repo}/releases/assets/#{asset_id}")
    req = Net::HTTP::Get.new(uri)
    req['Accept'] = 'application/octet-stream'
    req['Authorization'] = "token #{@github_token}"

    res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
      http.request(req)
    end

    res['location']
  end

  private

  def _fetch(url:, resolved_url:)
    # HTTP request header `Accept: application/octet-stream` is required.
    # Without this, the GitHub API will respond with metadata, not binary.
    curl_download download_url, "--header", "Accept: application/octet-stream", to: temporary_path
  end

  def asset_id
    @asset_id ||= resolve_asset_id
  end

  def resolve_asset_id
    release_metadata = fetch_release_metadata
    assets = release_metadata["assets"].select { |a| a["name"] == @filename }
    raise CurlDownloadStrategyError, "Asset file not found." if assets.empty?

    assets.first["id"]
  end

  def fetch_release_metadata
    release_url = "https://api.github.com/repos/#{@owner}/#{@repo}/releases/tags/#{@tag}"
    GitHub.open_api(release_url)
  end
end

1 Ответ

1 голос
/ 20 июня 2019

Вам необходимо переместить custom_download_strategy.rb в подпапку репозитория вашего крана, например, в homebrew-test/lib/custom_download_strategy.rb и соответственно изменить вызов require_relative.

По умолчанию все .rb файлы вПредполагается, что корень репозитория и подпапки Formula и HomebrewFormula являются допустимыми формулами Homebrew. Подробнее см. Документацию .

...