From e91f29f662a96cce0fbf867f989dd552d35054b3 Mon Sep 17 00:00:00 2001
From: Eduardo Trujillo <ed@chromabits.com>
Date: Sat, 26 Dec 2020 16:20:21 -0800
Subject: [PATCH] feat(Generate): Allow writing report to an output file

---
 shift.cabal           |  1 +
 src/Shift.hs          |  4 ++--
 src/Shift/CLI.hs      | 15 +++++++++++++--
 src/Shift/Generate.hs | 17 +++++++++++++++++
 src/Shift/Git.hs      |  6 ------
 5 files changed, 33 insertions(+), 10 deletions(-)
 create mode 100644 src/Shift/Generate.hs

diff --git a/shift.cabal b/shift.cabal
index 990a597..dc3f719 100644
--- a/shift.cabal
+++ b/shift.cabal
@@ -17,6 +17,7 @@ library
   hs-source-dirs:      src
   exposed-modules:     Shift
                      , Shift.CLI
+                     , Shift.Generate
                      , Shift.Git
                      , Shift.Parsers
                      , Shift.Processing
diff --git a/src/Shift.hs b/src/Shift.hs
index 3abf5a7..8251db4 100644
--- a/src/Shift.hs
+++ b/src/Shift.hs
@@ -42,7 +42,6 @@ import Shift.Git as X
     refsPairsFromRefs,
     renderDiff,
     renderToNode,
-    tempMain,
   )
 import Shift.Rendering as X
   ( bold,
@@ -115,6 +114,7 @@ import Shift.Types as X
     lookupUserOnGitHub,
     lookupUserOnGitHubCommit,
   )
+import Shift.Generate (runGenerate)
 
 -- | The main CLI entrypoint.
 shiftMain :: IO ()
@@ -122,7 +122,7 @@ shiftMain = do
   currentOptions <- execParser opts
 
   case currentOptions ^. soCommand of
-    GenerateCommand -> tempMain currentOptions
+    GenerateCommand {_gcOutputPath, ..} -> runGenerate _gcOutputPath currentOptions
     ServeCommand {_scPort, ..} -> runServer _scPort currentOptions
   where
     opts =
diff --git a/src/Shift/CLI.hs b/src/Shift/CLI.hs
index 0fe8b16..50724c5 100644
--- a/src/Shift/CLI.hs
+++ b/src/Shift/CLI.hs
@@ -36,7 +36,10 @@ data ShiftOptions = ShiftOptions
   }
   deriving (Show, Eq)
 
-data ShiftCommand = GenerateCommand | ServeCommand {_scPort :: Maybe Int} deriving (Show, Eq)
+data ShiftCommand
+  = GenerateCommand {_gcOutputPath :: Maybe FilePath}
+  | ServeCommand {_scPort :: Maybe Int}
+  deriving (Show, Eq)
 
 data HostingType = GitHubType | GitType deriving (Show, Eq, Enum)
 
@@ -97,7 +100,15 @@ shiftCommand =
     command
       "generate"
       ( info
-          (pure GenerateCommand)
+          ( GenerateCommand
+              <$> optional
+                ( strOption
+                    ( long "output-path" <> short 'o'
+                        <> metavar "PATH"
+                        <> help "File to write the report to."
+                    )
+                )
+          )
           (progDesc "Generate changelog")
       )
       <> command
diff --git a/src/Shift/Generate.hs b/src/Shift/Generate.hs
new file mode 100644
index 0000000..e433cfc
--- /dev/null
+++ b/src/Shift/Generate.hs
@@ -0,0 +1,17 @@
+module Shift.Generate where
+
+import CMarkGFM (nodeToCommonmark)
+import Control.Monad.IO.Class (MonadIO (liftIO))
+import qualified Data.Text.IO as TIO
+import Shift.CLI (ShiftOptions (ShiftOptions))
+import Shift.Git (renderToNode)
+
+runGenerate :: Maybe FilePath -> ShiftOptions -> IO ()
+runGenerate maybeOutputPath opts = do
+  node <- renderToNode opts
+
+  let output = nodeToCommonmark [] Nothing node
+
+  case maybeOutputPath of
+    Just outputPath -> liftIO $ TIO.writeFile outputPath output
+    Nothing -> liftIO $ TIO.putStr $ output
\ No newline at end of file
diff --git a/src/Shift/Git.hs b/src/Shift/Git.hs
index fdcf750..2cbd958 100644
--- a/src/Shift/Git.hs
+++ b/src/Shift/Git.hs
@@ -55,12 +55,6 @@ parseTag ref = case versioning . cs . refNameRaw $ ref of
   Left e -> Left e
   Right v -> Right (TagRef ref (Just v))
 
-tempMain :: ShiftOptions -> IO ()
-tempMain opts = do
-  node <- renderToNode opts
-
-  liftIO $ TIO.putStr $ nodeToCommonmark [] Nothing node
-
 renderToNode :: ShiftOptions -> IO Node
 renderToNode opts = withRepo ".git" $ \repo -> do
   pairedTags <- pairedTagsFromOpts opts repo
-- 
GitLab