From bc5cf2c1926225a43589abf330fe984ea439cb00 Mon Sep 17 00:00:00 2001
From: href <href@random.sh>
Date: Tue, 20 Nov 2018 17:55:03 +0100
Subject: [PATCH] Improved version string

---
 config/config.exs                             |  8 ---
 lib/pleroma/application.ex                    |  6 +++
 .../mastodon_api/mastodon_api_controller.ex   |  2 +-
 .../web/nodeinfo/nodeinfo_controller.ex       |  4 +-
 .../controllers/util_controller.ex            |  2 +-
 mix.exs                                       | 49 ++++++++++++++++++-
 6 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/config/config.exs b/config/config.exs
index af0fdca9a..ac841d907 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -72,18 +72,10 @@
 config :pleroma, :ostatus, Pleroma.Web.OStatus
 config :pleroma, :httpoison, Pleroma.HTTP
 
-version =
-  with {version, 0} <- System.cmd("git", ["rev-parse", "HEAD"]) do
-    "Pleroma #{Mix.Project.config()[:version]} #{String.trim(version)}"
-  else
-    _ -> "Pleroma #{Mix.Project.config()[:version]} dev"
-  end
-
 # Configures http settings, upstream proxy etc.
 config :pleroma, :http, proxy_url: nil
 
 config :pleroma, :instance,
-  version: version,
   name: "Pleroma",
   email: "example@example.com",
   description: "A Pleroma instance, an alternative fediverse server",
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index eedad7675..50adf68df 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -1,6 +1,12 @@
 defmodule Pleroma.Application do
   use Application
 
+  @name "Pleroma"
+  @version Mix.Project.config()[:version]
+  def name, do: @name
+  def version, do: @version
+  def named_version(), do: @name <> " " <> @version
+
   # See http://elixir-lang.org/docs/stable/elixir/Application.html
   # for more information on OTP Applications
   def start(_type, _args) do
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index a0b74311b..aa7e9418e 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -141,7 +141,7 @@ def masto_instance(conn, _params) do
       uri: Web.base_url(),
       title: Keyword.get(instance, :name),
       description: Keyword.get(instance, :description),
-      version: "#{@mastodon_api_level} (compatible; #{Keyword.get(instance, :version)})",
+      version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
       email: Keyword.get(instance, :email),
       urls: %{
         streaming_api: String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws")
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index d58f08881..151db0bb7 100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
@@ -86,8 +86,8 @@ def nodeinfo(conn, %{"version" => "2.0"}) do
     response = %{
       version: "2.0",
       software: %{
-        name: "pleroma",
-        version: Keyword.get(instance, :version)
+        name: Pleroma.Application.name(),
+        version: Pleroma.Application.version()
       },
       protocols: ["ostatus", "activitypub"],
       services: %{
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index dc4a864d6..b0ed8387e 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -197,7 +197,7 @@ def config(conn, _params) do
   end
 
   def version(conn, _params) do
-    version = Pleroma.Config.get([:instance, :version])
+    version = Pleroma.Application.named_version()
 
     case get_format(conn) do
       "xml" ->
diff --git a/mix.exs b/mix.exs
index ded414da9..865ead43b 100644
--- a/mix.exs
+++ b/mix.exs
@@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
   def project do
     [
       app: :pleroma,
-      version: "0.9.0",
+      version: version("0.9.0"),
       elixir: "~> 1.4",
       elixirc_paths: elixirc_paths(Mix.env()),
       compilers: [:phoenix, :gettext] ++ Mix.compilers(),
@@ -84,4 +84,51 @@ defp aliases do
       test: ["ecto.create --quiet", "ecto.migrate", "test"]
     ]
   end
+
+  # Builds a version string made of:
+  # * the application version
+  # * a pre-release if ahead of the tag: the describe string (-count-commithash)
+  # * build info:
+  #   * a build name if `PLEROMA_BUILD_NAME` or `:pleroma, :build_name` is defined
+  #   * the mix environment if different than prod
+  defp version(version) do
+    {git_tag, git_pre_release} =
+      with {tag, 0} <- System.cmd("git", ["describe", "--tags", "--abbrev=0"]),
+           tag = String.trim(tag),
+           {describe, 0} <- System.cmd("git", ["describe", "--tags"]),
+           describe = String.trim(describe),
+           ahead <- String.replace(describe, tag, "") do
+        {String.replace_prefix(tag, "v", ""), if(ahead != "", do: String.trim(ahead))}
+      else
+        _ -> {nil, nil}
+      end
+
+    if git_tag && version != git_tag do
+      Mix.shell().error(
+        "Application version #{inspect(version)} does not match git tag #{inspect(git_tag)}"
+      )
+    end
+
+    build_name =
+      cond do
+        name = Application.get_env(:pleroma, :build_name) -> name
+        name = System.get_env("PLEROMA_BUILD_NAME") -> name
+        true -> nil
+      end
+
+    env_name = if Mix.env() != :prod, do: to_string(Mix.env())
+
+    build =
+      [build_name, env_name]
+      |> Enum.filter(fn string -> string && string != "" end)
+      |> Enum.join("-")
+      |> (fn
+            "" -> nil
+            string -> "+" <> string
+          end).()
+
+    [version, git_pre_release, build]
+    |> Enum.filter(fn string -> string && string != "" end)
+    |> Enum.join()
+  end
 end