2

Elixir とそのエコシステム内のすべてのツールを、異なるビルド システムで動作するように適応させます。

このシステムでは、パッケージとその依存関係は個別に管理され、Hex はオフライン モードで動作するようになっています。(tarball を取得します)

1 つの注意点があります。新しいパッケージをインポートするたびに、最新のレジストリ ファイルを hexpm からインポートする必要があり、deps チェーンの最上位にない限り、hex を介して公開されていないパッケージは使用できません。

たくさんの tarball がある場合 (そしてそれらの間の依存関係が満たされていると仮定すると、それらで動作する 16 進数のレジストリ ファイルを構築するにはどうすればよいでしょうか。

私がこれまでに持っているもの:

  • レジストリ ファイルの形式を調べたところ、ets ファイルであることがわかりました。ロードして検査できます。今、私は生成する必要があります
  • ウェブサイトがレジストリファイルを構築する方法を見ましたが、私のニーズには非常に複雑です
  • レジストリ ファイルが必要な理由を理解するのに少し苦労しています (必要な場合、各パッケージに必要な情報をメタデータに含めることができず、中央レジストリの必要性が時代遅れになっているのはなぜですか)。

とにかく、誰かがHexで遊んで、これを行う方法についていくつかのガイダンスを提供できるなら、私はそれを感謝します.

4

2 に答える 2

2

ユースケースに関する詳細情報がなければ、適切な情報やアドバイスを提供するのは少し難しいです。あなたが何をしているのか、なぜそれをしているのかについて、もう少し詳しく説明していただけますか? 私は質問に答えるために最善を尽くします。

レジストリ形式の仕様は次のとおりです: https://github.com/hexpm/specifications/blob/master/registry.md

形式はかなり単純で、ETS ファイルを自分で作成するのにそれほど多くのコードは必要ありません。

レジストリ ファイルが必要な理由を理解するのに少し苦労しています (必要な場合、各パッケージに必要な情報をメタデータに含めることができず、中央レジストリの必要性が時代遅れになっているのはなぜですか)

Hex クライアントで依存関係を解決するには、レジストリが必要です。クライアントがパッケージの各バージョンを取得して解決したかどうかを確認する必要がある場合、リゾルバーは多くの異なるバージョンのパッケージを試すことができます。レジストリは最適化のために存在するため、完全な解決を行うために単一のファイルを取得するだけで済みます。

依存関係の解決を自分で行うことを暗示しているため、ローカルパッケージの tarball に直接依存することをお勧めします。あれは正しいですか?これをサポートするために、クライアントで問題を開きました: https://github.com/hexpm/hex/issues/261

于 2016-07-16T20:33:05.920 に答える
0

ここにたどり着いた将来の世代のために、ここに作業レジストリビルダーがあります:

defp string_files(files) do
  Enum.into(files, %{}, fn {name, binary} ->
    {List.to_string(name), binary}
  end)
end

defp decode(string) when is_binary(string) do
  string = String.to_char_list(string)
  case :safe_erl_term.string(string) do
    {:ok, tokens, _line} ->
      try do
        terms = :safe_erl_term.terms(tokens)
        result = Enum.into(terms, %{})
        {:ok, result}
      rescue
        FunctionClauseError ->
          {:error, "invalid terms"}
        ArgumentError ->
          {:error, "not in key-value format"}
      end

    {:error, reason} ->
      {:error, inspect reason}
  end
end

def build_registry(hex_home) do
  # find the tars
  tars = Path.wildcard(Path.join(hex_home,"packages/*.tar"))

  # initialize the ets table used to build the registry
  :ets.new(:myr, [:named_table])
  :ets.insert(:myr, {:"$$version$$", 4})

  # go through the tars, extract the info needed and populate
  # the registry
  Enum.each(tars, fn filename ->
      {:ok, files} = :erl_tar.extract(String.to_char_list(filename), [:memory])
      files = string_files(files)
      {:ok, metadata} = decode(files["metadata.config"])
      name = metadata["app"]
      version = metadata["version"]
      build_tools = metadata["build_tools"]
      checksum = files["CHECKSUM"]
      deps = []
      if metadata["requirements"], do: deps = metadata["requirements"]
      reg_deps = Enum.map(deps, fn
          {name, depa} ->
              depa = Enum.into(depa, %{})
              [name, depa["requirement"], depa["optional"], depa["app"]]
          depa ->
              depa = Enum.into(depa, %{})
              [depa["name"], depa["requirement"], depa["optional"], depa["app"]]
      end)
      IO.puts "adding dependency"
      IO.inspect {name, [[version]]}
      IO.inspect {{name, version}, [reg_deps, checksum, build_tools]}
      :ets.insert(:myr, {name, [[version]]})
      :ets.insert(:myr, {{name, version}, [reg_deps, checksum, build_tools]})
  end)

  # persist the registry to disk and remove the table
  registry_file = Path.join(hex_home, "registry.ets")
  IO.puts "Writing registry to: #{registry_file}"
  :ets.tab2file(:myr, String.to_char_list(registry_file))
  :ets.delete(:myr)
  registry_file_gzip = registry_file <> ".gz"
  IO.puts "Gzipping registry to: #{registry_file_gzip}"
  gzipped_content = File.read!(registry_file) |> :zlib.gzip
  File.write!(registry_file_gzip, gzipped_content)
end

より多くのコンテキストについて:

于 2016-07-19T20:56:57.367 に答える