<commit_before>Code.require_file("../../test_helper.exs", __DIR__)

defmodule Mix.Tasks.ArchiveTest do
  use MixTest.Case

  defmodule ArchiveProject do
    def project do
      [app: :archive, version: "0.1.0", elixir: "~> 0.1.0"]
    end
  end

  defmodule ArchiveProject2 do
    def project do
      [app: :archive, version: "0.2.0"]
    end
  end

  setup do
    File.rm_rf!(tmp_path("userhome"))
    System.put_env("MIX_ARCHIVES", tmp_path("userhome/.mix/archives/"))
    Mix.Project.push(ArchiveProject)

    on_exit(fn ->
      Mix.Local.remove_archives()
      System.delete_env("MIX_ARCHIVES")
    end)
  end

  test "archive build" do
    in_fixture("archive", fn ->
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check"])
      message = "Generated archive \"archive-0.1.0.ez\" with MIX_ENV=dev"
      assert_received {:mix_shell, :info, [^message]}
      assert File.regular?('archive-0.1.0.ez')

      assert_archive_content_default()
      refute has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/priv/.dot_file')
    end)
  end

  test "archive build with include-dot-files" do
    in_fixture("archive", fn ->
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check", "--include-dot-files"])
      message = "Generated archive \"archive-0.1.0.ez\" with MIX_ENV=dev"
      assert_received {:mix_shell, :info, [^message]}
      assert File.regular?('archive-0.1.0.ez')

      assert_archive_content_default()
      assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/priv/.dot_file')
    end)
  end

  def assert_archive_content_default() do
    assert File.regular?('archive-0.1.0.ez')
    assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/.elixir')
    assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/priv/not_really_an.so')

    assert has_in_zip_file?(
             'archive-0.1.0.ez',
             'archive-0.1.0/ebin/Elixir.Mix.Tasks.Local.Sample.beam'
           )

    assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/ebin/archive.app')
  end

  test "archive install" do
    in_fixture("archive", fn ->
      # Build and install archive
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check"])

      send(self(), {:mix_shell_input, :yes?, true})
      Mix.Tasks.Archive.Install.run([])
      refute File.regular?(tmp_path("userhome/.mix/archives/archive-0.1.0.ez"))
      assert File.dir?(tmp_path("userhome/.mix/archives/archive-0.1.0/archive-0.1.0/ebin"))

      # Check that the version warning is printed after installation
      version_error =
        "warning: the archive archive-0.1.0 requires Elixir \"~> 0.1.0\" " <>
          "but you are running on v#{System.version()}"

      assert_received {:mix_shell, :error, [^version_error]}

      archive = tmp_path("userhome/.mix/archives/archive-0.1.0/archive-0.1.0/ebin")
      assert to_charlist(archive) in :code.get_path()

      # Loading the archive should emit warning again
      Mix.Local.append_archives()
      assert_received {:mix_shell, :error, [^version_error]}

      # List archive
      Mix.Tasks.Local.run([])
      info = "mix local.sample # A local install sample"
      assert_received {:mix_shell, :info, [^info]}

      Mix.Tasks.Archive.run([])
      assert_received {:mix_shell, :info, ["* archive-0.1.0"]}

      # Run archived task
      Mix.Task.run("local.sample")
      assert_received {:mix_shell, :info, ["sample"]}
    end)
  end

  test "archive install invalid file" do
    in_fixture("archive", fn ->
      file_name = "invalid-archive-0.1.0.ez"
      assert File.regular?(file_name)

      send(self(), {:mix_shell_input, :yes?, true})

      assert_raise Mix.Error, ~r/invalid archive file/, fn ->
        Mix.Tasks.Archive.Install.run([file_name])
      end
    end)
  end

  test "archive install missing file" do
    message = ~r[Expected "./unlikely-to-exist-0.1.0.ez" to be a local file path]

    assert_raise Mix.Error, message, fn ->
      Mix.Tasks.Archive.Install.run(["./unlikely-to-exist-0.1.0.ez"])
    end
  end

  test "archive install --force" do
    in_fixture("archive", fn ->
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check"])
      Mix.Tasks.Archive.Install.run(["--force"])

      message = "Generated archive \"archive-0.1.0.ez\" with MIX_ENV=dev"
      assert_received {:mix_shell, :info, [^message]}

      Mix.Tasks.Archive.Uninstall.run(["archive-0.1.0", "--force"])
      refute File.dir?(tmp_path("userhome/.mix/archives/archive-0.1.0/archive-0.1.0/ebin"))
    end)
  end

  test "archive.install from Git" do
    in_fixture("git_repo", fn ->
      File.mkdir_p!("config")

      File.write!("config/config.exs", """
      import Config
      config :git_repo, :archive_config, true
      """)

      File.write!("lib/git_repo.ex", """
      require Application
      true = Application.compile_env!(:git_repo, :archive_config)

      defmodule GitRepo.Archive do
        def hello do
          "World"
        end
      end
      """)

      System.cmd("git", ~w[init])
      System.cmd("git", ~w[add .])
      System.cmd("git", ~w[commit -m first-commit])

      send(self(), {:mix_shell_input, :yes?, true})<commit_msg>Fix warning from call to dynamically generated module<commit_after>Code.require_file("../../test_helper.exs", __DIR__)

defmodule Mix.Tasks.ArchiveTest do
  use MixTest.Case

  defmodule ArchiveProject do
    def project do
      [app: :archive, version: "0.1.0", elixir: "~> 0.1.0"]
    end
  end

  defmodule ArchiveProject2 do
    def project do
      [app: :archive, version: "0.2.0"]
    end
  end

  setup do
    File.rm_rf!(tmp_path("userhome"))
    System.put_env("MIX_ARCHIVES", tmp_path("userhome/.mix/archives/"))
    Mix.Project.push(ArchiveProject)

    on_exit(fn ->
      Mix.Local.remove_archives()
      System.delete_env("MIX_ARCHIVES")
    end)
  end

  test "archive build" do
    in_fixture("archive", fn ->
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check"])
      message = "Generated archive \"archive-0.1.0.ez\" with MIX_ENV=dev"
      assert_received {:mix_shell, :info, [^message]}
      assert File.regular?('archive-0.1.0.ez')

      assert_archive_content_default()
      refute has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/priv/.dot_file')
    end)
  end

  test "archive build with include-dot-files" do
    in_fixture("archive", fn ->
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check", "--include-dot-files"])
      message = "Generated archive \"archive-0.1.0.ez\" with MIX_ENV=dev"
      assert_received {:mix_shell, :info, [^message]}
      assert File.regular?('archive-0.1.0.ez')

      assert_archive_content_default()
      assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/priv/.dot_file')
    end)
  end

  def assert_archive_content_default() do
    assert File.regular?('archive-0.1.0.ez')
    assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/.elixir')
    assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/priv/not_really_an.so')

    assert has_in_zip_file?(
             'archive-0.1.0.ez',
             'archive-0.1.0/ebin/Elixir.Mix.Tasks.Local.Sample.beam'
           )

    assert has_in_zip_file?('archive-0.1.0.ez', 'archive-0.1.0/ebin/archive.app')
  end

  test "archive install" do
    in_fixture("archive", fn ->
      # Build and install archive
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check"])

      send(self(), {:mix_shell_input, :yes?, true})
      Mix.Tasks.Archive.Install.run([])
      refute File.regular?(tmp_path("userhome/.mix/archives/archive-0.1.0.ez"))
      assert File.dir?(tmp_path("userhome/.mix/archives/archive-0.1.0/archive-0.1.0/ebin"))

      # Check that the version warning is printed after installation
      version_error =
        "warning: the archive archive-0.1.0 requires Elixir \"~> 0.1.0\" " <>
          "but you are running on v#{System.version()}"

      assert_received {:mix_shell, :error, [^version_error]}

      archive = tmp_path("userhome/.mix/archives/archive-0.1.0/archive-0.1.0/ebin")
      assert to_charlist(archive) in :code.get_path()

      # Loading the archive should emit warning again
      Mix.Local.append_archives()
      assert_received {:mix_shell, :error, [^version_error]}

      # List archive
      Mix.Tasks.Local.run([])
      info = "mix local.sample # A local install sample"
      assert_received {:mix_shell, :info, [^info]}

      Mix.Tasks.Archive.run([])
      assert_received {:mix_shell, :info, ["* archive-0.1.0"]}

      # Run archived task
      Mix.Task.run("local.sample")
      assert_received {:mix_shell, :info, ["sample"]}
    end)
  end

  test "archive install invalid file" do
    in_fixture("archive", fn ->
      file_name = "invalid-archive-0.1.0.ez"
      assert File.regular?(file_name)

      send(self(), {:mix_shell_input, :yes?, true})

      assert_raise Mix.Error, ~r/invalid archive file/, fn ->
        Mix.Tasks.Archive.Install.run([file_name])
      end
    end)
  end

  test "archive install missing file" do
    message = ~r[Expected "./unlikely-to-exist-0.1.0.ez" to be a local file path]

    assert_raise Mix.Error, message, fn ->
      Mix.Tasks.Archive.Install.run(["./unlikely-to-exist-0.1.0.ez"])
    end
  end

  test "archive install --force" do
    in_fixture("archive", fn ->
      Mix.Tasks.Archive.Build.run(["--no-elixir-version-check"])
      Mix.Tasks.Archive.Install.run(["--force"])

      message = "Generated archive \"archive-0.1.0.ez\" with MIX_ENV=dev"
      assert_received {:mix_shell, :info, [^message]}

      Mix.Tasks.Archive.Uninstall.run(["archive-0.1.0", "--force"])
      refute File.dir?(tmp_path("userhome/.mix/archives/archive-0.1.0/archive-0.1.0/ebin"))
    end)
  end

  @compile {:no_warn_undefined, GitRepo.Archive}
  test "archive.install from Git" do
    in_fixture("git_repo", fn ->
      File.mkdir_p!("config")

      File.write!("config/config.exs", """
      import Config
      config :git_repo, :archive_config, true
      """)

      File.write!("lib/git_repo.ex", """
      require Application
      true = Application.compile_env!(:git_repo, :archive_config)

      defmodule GitRepo.Archive do
        def hello do
          "World"
        end
      end
      """)

      System.cmd("git", ~w[init])
      System.cmd("git", ~w[add .])
      System.cmd("git", ~w[commit -m first-commit])

      send(self(), {:mix_shell_input, :yes?, true})
{'fraction_non_alphanumeric': 0.16106348136017726, 'fraction_numerical': 0.02042192467007032, 'mean_word_length': 2.81972038263429, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4878120', 'n_tokens_mistral': 3745, 'n_tokens_neox': 3586, 'n_words': 659}