{-# LANGUAGE CPP             #-}
{-
Version number-related utilities. See also the Makefile.
-}

module Hledger.Cli.Version (
  packageversion,
  progname,
  versionStringFor,
)
where

import GitHash (GitInfo, giDescribe)
import System.Info (os, arch)
import Hledger.Utils

-- | This package's version, passed in as VERSION build variable, or a generic description.
packageversion :: String
#ifdef VERSION
packageversion :: String
packageversion = VERSION
#else
packageversion = "dev build"
#endif

-- | A period and the patch level (number of patches added since the package version), 
-- passed in as PATCHLEVEL build variable, or the empty string. 
-- If PATCHLEVEL is defined it must be a number, or this will fail.
patchlevel :: String
#ifdef PATCHLEVEL
patchlevel = "." ++ show (PATCHLEVEL :: Int)
#else
patchlevel :: String
patchlevel = String
""
#endif

-- | The version and patchlevel passed in as build variables, combined and prettified.
-- This will raise an error if VERSION is has <1 or >3 components,
-- or if PATCHLEVEL is defined but not a number.
-- Used as a fallback if git describe is unavailable.
buildversion :: String
buildversion :: String
buildversion = [String] -> String
prettify ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> String -> [String]
forall a. Eq a => a -> [a] -> [[a]]
splitAtElement Char
'.' (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
packageversion String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
patchlevel
  where
    prettify :: [String] -> String
prettify [String
major,String
minor,String
bugfix,String
patches] =
        String
major String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
minor String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
bugfix' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
patches'
      where
        bugfix' :: String
bugfix'  = if String
bugfix  String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"0" then String
"" else Char
'.' Char -> String -> String
forall a. a -> [a] -> [a]
: String
bugfix
        patches' :: String
patches' = if String
patches String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"0" then String
"" else Char
'+' Char -> String -> String
forall a. a -> [a] -> [a]
: String
patches
    prettify [String
major,String
minor,String
bugfix] = [String] -> String
prettify [String
major,String
minor,String
bugfix,String
"0"]
    prettify [String
major,String
minor]        = [String] -> String
prettify [String
major,String
minor,String
"0",String
"0"]
    prettify [String
major]              = [String] -> String
prettify [String
major,String
"0",String
"0",String
"0"]
    prettify []                   = String -> String
forall a. String -> a
error' String
"VERSION is empty, please fix"  -- PARTIAL:
    prettify [String]
_                    = String -> String
forall a. String -> a
error' String
"VERSION has too many components, please fix"

-- | The name of this package's main executable.
progname :: String
progname :: String
progname = String
"hledger"

-- | Given a program name, make a version string consisting of: 
--
-- * the program name
-- * the output of "git describe" in the current repo at build time 
--   (last tag, commit count since then, HEAD's git hash);
--   or if that fails, buildversion
-- * the platform (OS) name
-- * the processor architecture name.
--
versionStringFor :: Either String GitInfo -> String -> String
versionStringFor :: Either String GitInfo -> String -> String
versionStringFor Either String GitInfo
gitinfo String
progname = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [
    String
progname
  , String
" "
  , (String -> String)
-> (GitInfo -> String) -> Either String GitInfo -> String
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> String -> String
forall a b. a -> b -> a
const String
buildversion) GitInfo -> String
giDescribe Either String GitInfo
gitinfo
  , String
", "
  , String
os'
  , String
"-"
  , String
arch
  ]
  where
    os' :: String
os' | String
os String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"darwin"  = String
"mac"
        | String
os String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"mingw32" = String
"windows"
        | Bool
otherwise       = String
os

-- -- | Given a program name, return a precise platform-specific executable
-- -- name suitable for naming downloadable binaries.  Can raise an error if
-- -- the version and patch level was not defined correctly at build time.
-- binaryfilename :: String -> String
-- binaryfilename progname = concat
--     [progname, "-", buildversion, "-", os', "-", arch, suffix]
--   where
--     (os',suffix) | os == "darwin"  = ("mac","" :: String)
--                  | os == "mingw32" = ("windows",".exe")
--                  | otherwise       = (os,"")