From c0ad1cbe8ffba320dcbed7559a407586d068f4c8 Mon Sep 17 00:00:00 2001 From: Alex Koutmos Date: Mon, 18 Apr 2022 01:25:34 -0400 Subject: [PATCH] Getting ready for 0.2.0 release --- CHANGELOG.md | 18 ++++++++ LICENSE | 21 ++++++++++ README.md | 4 +- lib/litestream/downloader.ex | 80 +++++++++++++++++++++++------------- mix.exs | 2 +- 5 files changed, 93 insertions(+), 32 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 LICENSE diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..58c33b8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.3.0] - 2021-04-17 + +### Added + +- Support for version 0.3.8 of Litestream + +### Fixed + +- The error when downloading Linux versions of the binary diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c9e31c7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Alexander Koutmos + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index a18eb39..8e5c31b 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ dependencies in `mix.exs`: ```elixir def deps do [ - {:litestream, "~> 0.1.0"} + {:litestream, "~> 0.2.0"} ] end ``` @@ -73,7 +73,7 @@ Checkout my [GitHub Sponsorship page](https://github.com/sponsors/akoutmos) if y ## Setting Up Litestream -After adding `{:litestream, "~> 0.1.0"}` in your `mix.exs` file and running `mix deps.get`, open your `application.ex` +After adding `{:litestream, "~> 0.2.0"}` in your `mix.exs` file and running `mix deps.get`, open your `application.ex` file and add the following to your supervision tree: ```elixir diff --git a/lib/litestream/downloader.ex b/lib/litestream/downloader.ex index 8544e3b..49a9663 100644 --- a/lib/litestream/downloader.ex +++ b/lib/litestream/downloader.ex @@ -5,10 +5,15 @@ defmodule Litestream.Downloader do require Logger - @latest_litestream_version "0.3.7" - @supported_litestream_versions ["0.3.7"] + @latest_litestream_version "0.3.8" + @supported_litestream_versions ["0.3.8", "0.3.7"] @valid_litestream_versions %{ + # All the SHA hashes for version 0.3.8 + {"0.3.8", :darwin, :amd64} => "d359a4edd1cb98f59a1a7c787bbd0ed30c6cc3126b02deb05a0ca501ff94a46a", + {"0.3.8", :linux, :amd64} => "530723d95a51ee180e29b8eba9fee8ddafc80a01cab7965290fb6d6fc31381b3", + {"0.3.8", :linux, :arm64} => "1d6fb542c65b7b8bf91c8859d99f2f48b0b3251cc201341281f8f2c686dd81e2", + # All the SHA hashes for version 0.3.7 {"0.3.7", :darwin, :amd64} => "fdfd811df081949fdac2f09af8ad624c37c02b98c0e777f725f69e67be270745", {"0.3.7", :linux, :amd64} => "e9daf0b73d7b5d75eac22bb9f0a93945e3efce0f1ff5f3a6b57f4341da4609cf", @@ -39,34 +44,39 @@ defmodule Litestream.Downloader do litestream_version = get_download_version(litestream_version) download_url = build_download_url(litestream_version) - zip_file_name = + archive_file_name = download_url |> URI.parse() |> Map.get(:path) |> Path.basename() binary_file_name = - zip_file_name - |> String.trim_trailing(".zip") + if String.ends_with?(archive_file_name, ".zip") do + archive_file_name + |> String.trim_trailing(".zip") + else + archive_file_name + |> String.trim_trailing(".tar.gz") + end # Set constants for where files will be located - zip_download_path = "#{download_directory}/#{zip_file_name}" + archive_download_path = "#{download_directory}/#{archive_file_name}" binary_path = "#{bin_directory}/#{binary_file_name}" - # Download the litestream, verify it, and unzip it - with :ok <- do_download_litestream(download_url, zip_download_path), - :ok <- verify_zip_download(zip_download_path, litestream_version) do - unzip_litestream(zip_download_path, binary_path) + # Download the litestream, verify it, and unarchive it + with :ok <- do_download_litestream(download_url, archive_download_path), + :ok <- verify_archive_download(archive_download_path, litestream_version) do + unarchive_litestream(archive_download_path, binary_path) end end - defp do_download_litestream(download_url, zip_file_path) do - if File.exists?(zip_file_path) do - Logger.info("Litestream zip archive already present") + defp do_download_litestream(download_url, archive_file_path) do + if File.exists?(archive_file_path) do + Logger.info("Litestream archive already present") :ok else - Logger.info("Fetching Litestream zip archive") + Logger.info("Fetching Litestream archive") # Ensure that the necessary applications have been started {:ok, _} = Application.ensure_all_started(:inets) @@ -102,7 +112,7 @@ defmodule Litestream.Downloader do case :httpc.request(:get, {download_url, []}, http_options, options) do {:ok, {{_, 200, _}, _headers, body}} -> - File.write!(zip_file_path, body) + File.write!(archive_file_path, body) error -> raise "Could not fetch Litestream from #{download_url}: #{inspect(error)}" @@ -117,7 +127,7 @@ defmodule Litestream.Downloader do [arch | _] = arch_str |> List.to_string() |> String.split("-") case {:os.type(), arch, :erlang.system_info(:wordsize) * 8} do - # TODO: When Litestream support ARM macOS builds + # TODO: When Litestream supports ARM macOS builds # {{:unix, :darwin}, arch, 64} when arch in ~w(arm aarch64) -> {litestream_version, :darwin, :arm64} {{:unix, :darwin}, arch, 64} when arch in ~w(arm aarch64) -> {litestream_version, :darwin, :amd64} {{:unix, :darwin}, "x86_64", 64} -> {litestream_version, :darwin, :amd64} @@ -127,35 +137,47 @@ defmodule Litestream.Downloader do end end - defp unzip_litestream(zip_download_path, binary_path) do - # Extract the zip file - zip_contents = File.read!(zip_download_path) - {:ok, [{_file_name, unzipped_contents}]} = :zip.extract(zip_contents, [:memory]) + defp unarchive_litestream(archive_download_path, binary_path) do + if String.ends_with?(archive_download_path, ".zip") do + # Extract the zip file + zip_contents = File.read!(archive_download_path) + {:ok, [{_file_name, unzipped_contents}]} = :zip.extract(zip_contents, [:memory]) + + # Set exec permissions to Litestream + File.write(binary_path, unzipped_contents) + File.chmod!(binary_path, 0o755) - # Set exec permissions to Litestream - File.write(binary_path, unzipped_contents) - File.chmod!(binary_path, 0o755) + {:ok, binary_path} + else + # Extract the tarball + tarball_contents = File.read!(archive_download_path) + {:ok, [{_file_name, untarred_contents}]} = :erl_tar.extract({:binary, tarball_contents}, [:memory, :compressed]) + + # Set exec permissions to Litestream + File.write(binary_path, untarred_contents) + File.chmod!(binary_path, 0o755) - {:ok, binary_path} + {:ok, binary_path} + end end - defp verify_zip_download(zip_download_path, litestream_version) do + defp verify_archive_download(archive_download_path, litestream_version) do # Get the known SHA256 value known_sha = Map.fetch!(@valid_litestream_versions, litestream_version) - # Read the zip file and compute the SHA256 value - zip_contents = File.read!(zip_download_path) + # Read the archive file and compute the SHA256 value + archive_contents = File.read!(archive_download_path) computed_sha = :sha256 - |> :crypto.hash(zip_contents) + |> :crypto.hash(archive_contents) |> Base.encode16() |> String.downcase() if known_sha == computed_sha do :ok else - {:error, "Invalid SHA256 value computed for #{zip_download_path}"} + {:error, "Invalid SHA256 value computed for #{archive_download_path}"} end end diff --git a/mix.exs b/mix.exs index b400c30..0fae3cc 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Litestream.MixProject do def project do [ app: :litestream, - version: "0.1.0", + version: "0.2.0", elixir: "~> 1.13", name: "Litestream", source_url: "https://github.com/akoutmos/litestream",