<commit_before>module FeatureSpec ( spec ) where

import           Hi.Version          (version)

import           Control.Applicative
import           Control.Exception   (bracket_)
import           Data.List           (intercalate)
import           Data.Time.Calendar  (toGregorian)
import           Data.Time.Clock     (getCurrentTime, utctDay)
import           System.Directory    (createDirectoryIfMissing,
                                      doesDirectoryExist, doesFileExist,
                                      getCurrentDirectory,
                                      removeDirectoryRecursive,
                                      setCurrentDirectory)
import           System.Process      (readProcess, readProcessWithExitCode,
                                      system)
import           Test.Hspec

spec :: Spec
spec = do
    describe "with command line options" $
      around setupWithCommandLineOptions features

    describe "with configuration file" $
      around setupWithConfigurationFile features

    describe "-v" $ do
      it "should show version number" $ do
        r <- readProcess "./dist/build/hi/hi" ["-v"] []
        r `shouldBe` version ++ "\n"

    describe "with incomplete command line options" $ do
      it "should show error message" $ do
        (_,_,r) <- readProcessWithExitCode "./dist/build/hi/hi" ["-m", "Foo"] []
        r `shouldContain` "\n (Run with no arguments to see usage)"

packageName, moduleName, author, email, fileName :: String
packageName = "testapp"
moduleName  = "System.Awesome.Library"
author      = "<NAME>"
email       = "<EMAIL>"
fileName    = ".hirc"

features :: Spec
features = do

  describe "LICENSE" $ do
    it "should include author" $  do
      compiled <- readFile "testapp/LICENSE"
      compiled `shouldContain` "Fujimura Daisuke"

    it "should include year" $  do
      (year,_,_) <- (toGregorian . utctDay) <$> getCurrentTime
      compiled   <- readFile "testapp/LICENSE"
      compiled `shouldContain` show year

  describe "README.md" $ do
    it "should include name" $  do
      compiled <- readFile "testapp/README.md"
      compiled `shouldContain` "testapp"

  describe "module-name.cabal" $ do
    it "should include name" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "testapp"

    it "should include author" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "<NAME>"

    it "should include email" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "<EMAIL>"

    it "should include exposed-modules" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "Exposed-Modules:      System.Awesome.Library"

    it "should include other-modules" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "Other-Modules:        System.Awesome.Library.Internal"

  describe "directory" $ do
    it "should be made according to given module name" $  do
      doesDirectoryExist "testapp/src/System/Awesome/Library" `shouldReturn` True

  describe "Main module" $ do
    it "should be made" $  do
      doesFileExist "testapp/src/System/Awesome/Library.hs" `shouldReturn` True

    it "should include proper module name" $  do
      compiled <- readFile "testapp/src/System/Awesome/Library.hs"
      compiled `shouldContain` "module System.Awesome.Library"

  describe "Internal module" $ do
    it "should be made" $  do
      doesFileExist "testapp/src/System/Awesome/Library/Internal.hs" `shouldReturn` True

    it "should include proper module name" $  do
      compiled <- readFile "testapp/src/System/Awesome/Library/Internal.hs"
      compiled `shouldContain` "module System.Awesome.Library.Internal"

  describe "Spec.hs" $ do
    it "should be made" $  do
      doesFileExist "testapp/test/Spec.hs" `shouldReturn` True

    it "should include proper content" $  do
      compiled <- readFile "testapp/test/Spec.hs"
      compiled `shouldContain` "{-# OPTIONS_GHC -F -pgmF hspec-discover #-}"

  describe "Main spec" $ do
    it "should be made" $  do
      system "tree testapp"

      doesFileExist "testapp/test/System/Awesome/LibrarySpec.hs" `shouldReturn` True

    it "should include proper content" $  do
      compiled <- readFile "testapp/test/System/Awesome/LibrarySpec.hs"
      compiled `shouldContain` "module System.Awesome.LibrarySpec (main, spec) where"

  describe ".gitignore" $ do
    it "should be made" $  do
      doesFileExist "testapp/.gitignore" `shouldReturn` True

setupWithConfigurationFile :: IO () -> IO ()
setupWithConfigurationFile action = do
    pwd <- getCurrentDirectory

    inTestDirectory $ do
        writeFile fileName $ concatLines
            [ "packageName: " ++ packageName
            , "moduleName: "  ++ moduleName
            , "author: "      ++ author
            , "email: "       ++ email
            , "repository: "  ++ "file://" ++ pwd ++ "/template"
            ]
        pwd' <- getCurrentDirectory
        _ <- system $ concat [ pwd ++ "/dist/build/hi/hi"
                             , " --configuration-file ", pwd' ++ "/" ++ fileName
                             ]
        action
  where
    concatLines :: [String] -> String
    concatLines = intercalate "\n"

setupWithCommandLineOptions :: IO () -> IO ()
setupWithCommandLineOptions action = do
    pwd <- getCurrentDirectory

    inTestDirectory $ do
        _ <- system $ concat [ pwd ++ "/dist/build/hi/hi"
                             , " -p ", packageName
                             , " -m ", moduleName
                             , " -a ", quote author
                             , " -e ", quote email
                             , " -r file://" ++ pwd ++ "/template"
                             ]
        action

inTestDirectory :: IO () -> IO ()
inTestDirectory action = do
    pwd <- getCurrentDirectory
    let go    = createDirectoryIfMissing True testDirectory >> setCurrentDirectory testDirectory
        flush = removeDirectoryRecursive testDirectory
        back  = setCurrentDirectory pwd
    bracket_ go (back >> flush) action

testDirectory :: String
testDirectory = "test_project"

quote :: String -> String
quote s = "\"" ++ s ++ "\""
<commit_msg>Add spec for --initialize-git-repository<commit_after>module FeatureSpec ( spec ) where

import           Hi.Version          (version)
import           Hi.Directory        (inDirectory)

import           Control.Applicative
import           Control.Exception   (bracket_)
import           Data.List           (intercalate)
import           Data.Time.Calendar  (toGregorian)
import           Data.Time.Clock     (getCurrentTime, utctDay)
import           System.Directory    (createDirectoryIfMissing,
                                      doesDirectoryExist, doesFileExist,
                                      getCurrentDirectory,
                                      removeDirectoryRecursive,
                                      setCurrentDirectory)
import           System.Process      (readProcess, readProcessWithExitCode,
                                      system)
import           Test.Hspec

spec :: Spec
spec = do
    describe "with command line options" $
      around setupWithCommandLineOptions features

    describe "with configuration file" $
      around setupWithConfigurationFile features

    describe "-v" $ do
      it "should show version number" $ do
        r <- readProcess "./dist/build/hi/hi" ["-v"] []
        r `shouldBe` version ++ "\n"

    describe "with incomplete command line options" $ do
      it "should show error message" $ do
        (_,_,r) <- readProcessWithExitCode "./dist/build/hi/hi" ["-m", "Foo"] []
        r `shouldContain` "\n (Run with no arguments to see usage)"

    describe "with --initialize-git-repository" $ do
      around (setupWithCommandLineOptions' [" --initialize-git-repository "]) $ do
        it "should initialize it as git repository and make first commit" $ do
          inDirectory "./testapp" $ do
            readProcess "git" ["log", "-1", "--pretty=%s"] [] `shouldReturn` "Initial commit\n"

packageName, moduleName, author, email, fileName :: String
packageName = "testapp"
moduleName  = "System.Awesome.Library"
author      = "<NAME>"
email       = "<EMAIL>"
fileName    = ".hirc"

features :: Spec
features = do

  describe "LICENSE" $ do
    it "should include author" $  do
      compiled <- readFile "testapp/LICENSE"
      compiled `shouldContain` "Fujimura Daisuke"

    it "should include year" $  do
      (year,_,_) <- (toGregorian . utctDay) <$> getCurrentTime
      compiled   <- readFile "testapp/LICENSE"
      compiled `shouldContain` show year

  describe "README.md" $ do
    it "should include name" $  do
      compiled <- readFile "testapp/README.md"
      compiled `shouldContain` "testapp"

  describe "module-name.cabal" $ do
    it "should include name" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "testapp"

    it "should include author" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "<NAME>"

    it "should include email" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "<EMAIL>"

    it "should include exposed-modules" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "Exposed-Modules:      System.Awesome.Library"

    it "should include other-modules" $  do
      compiled <- readFile "testapp/testapp.cabal"
      compiled `shouldContain` "Other-Modules:        System.Awesome.Library.Internal"

  describe "directory" $ do
    it "should be made according to given module name" $  do
      doesDirectoryExist "testapp/src/System/Awesome/Library" `shouldReturn` True

  describe "Main module" $ do
    it "should be made" $  do
      doesFileExist "testapp/src/System/Awesome/Library.hs" `shouldReturn` True

    it "should include proper module name" $  do
      compiled <- readFile "testapp/src/System/Awesome/Library.hs"
      compiled `shouldContain` "module System.Awesome.Library"

  describe "Internal module" $ do
    it "should be made" $  do
      doesFileExist "testapp/src/System/Awesome/Library/Internal.hs" `shouldReturn` True

    it "should include proper module name" $  do
      compiled <- readFile "testapp/src/System/Awesome/Library/Internal.hs"
      compiled `shouldContain` "module System.Awesome.Library.Internal"

  describe "Spec.hs" $ do
    it "should be made" $  do
      doesFileExist "testapp/test/Spec.hs" `shouldReturn` True

    it "should include proper content" $  do
      compiled <- readFile "testapp/test/Spec.hs"
      compiled `shouldContain` "{-# OPTIONS_GHC -F -pgmF hspec-discover #-}"

  describe "Main spec" $ do
    it "should be made" $  do
      system "tree testapp"

      doesFileExist "testapp/test/System/Awesome/LibrarySpec.hs" `shouldReturn` True

    it "should include proper content" $  do
      compiled <- readFile "testapp/test/System/Awesome/LibrarySpec.hs"
      compiled `shouldContain` "module System.Awesome.LibrarySpec (main, spec) where"

  describe ".gitignore" $ do
    it "should be made" $  do
      doesFileExist "testapp/.gitignore" `shouldReturn` True

setupWithConfigurationFile :: IO () -> IO ()
setupWithConfigurationFile action = do
    pwd <- getCurrentDirectory

    inTestDirectory $ do
        writeFile fileName $ concatLines
            [ "packageName: " ++ packageName
            , "moduleName: "  ++ moduleName
            , "author: "      ++ author
            , "email: "       ++ email
            , "repository: "  ++ "file://" ++ pwd ++ "/template"
            ]
        pwd' <- getCurrentDirectory
        _ <- system $ concat [ pwd ++ "/dist/build/hi/hi"
                             , " --configuration-file ", pwd' ++ "/" ++ fileName
                             ]
        action
  where
    concatLines :: [String] -> String
    concatLines = intercalate "\n"

setupWithCommandLineOptions :: IO () -> IO ()
setupWithCommandLineOptions = setupWithCommandLineOptions' []

setupWithCommandLineOptions' :: [String] -> IO () -> IO ()
setupWithCommandLineOptions' opts action = do
    pwd <- getCurrentDirectory

    inTestDirectory $ do
        _ <- system $ concat [ pwd ++ "/dist/build/hi/hi"
                             , " -p ", packageName
                             , " -m ", moduleName
                             , " -a ", quote author
                             , " -e ", quote email
                             , " -r file://" ++ pwd ++ "/template"
                             ] ++ concat opts
        action

inTestDirectory :: IO () -> IO ()
inTestDirectory action = do
    pwd <- getCurrentDirectory
    let go    = createDirectoryIfMissing True testDirectory >> setCurrentDirectory testDirectory
        flush = removeDirectoryRecursive testDirectory
        back  = setCurrentDirectory pwd
    bracket_ go (back >> flush) action

testDirectory :: String
testDirectory = "test_project"

quote :: String -> String
quote s = "\"" ++ s ++ "\""

{'fraction_non_alphanumeric': 0.1053674900884416, 'fraction_numerical': 7.624275693809088e-05, 'mean_word_length': 2.2118021547502447, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1415515', 'n_tokens_mistral': 3731, 'n_tokens_neox': 3592, 'n_words': 996}