<commit_before>-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.Client.Sandbox.Timestamp
-- Maintainer  :  <EMAIL>
-- Portability :  portable
--
-- Timestamp file handling (for add-source dependencies).
-----------------------------------------------------------------------------

module Distribution.Client.Sandbox.Timestamp (
  AddSourceTimestamp,
  withRemoveTimestamps,
  withUpdateTimestamps,
  isDepModified,
  withModifiedDeps,
  ) where

import Control.Monad                                 (filterM, forM)
import Data.Char                                     (isSpace)
import Data.List                                     (partition)
import System.Directory                              (renameFile)
import System.FilePath                               (isAbsolute, (<.>), (</>))

import Distribution.PackageDescription               (BuildInfo (..),
                                                      Executable (..),
                                                      Library (..),
                                                      PackageDescription (..))
import Distribution.PackageDescription.Configuration (flattenPackageDescription)
import Distribution.PackageDescription.Parse         (readPackageDescription)
import Distribution.Simple.PreProcess                (knownSuffixHandlers)
import Distribution.Simple.SrcDist                   (allSourcesBuildInfo,
                                                      filterAutogenModule,
                                                      findIncludeFile,
                                                      findMainExeFile,
                                                      findSetupFile)
import Distribution.Simple.Utils                     (defaultPackageDesc, die,
                                                      findPackageDesc,
                                                      matchFileGlob)
import Distribution.Verbosity                        (Verbosity)

import Distribution.Client.Utils                     (inDir)

import Distribution.Compat.Exception                 (catchIO)
import Distribution.Compat.Time                      (EpochTime, getCurTime,
                                                      getModTime)


-- | Timestamp of an add-source dependency.
type AddSourceTimestamp = (FilePath, EpochTime)

-- | The 'add-source-timestamps' file keeps the timestamps of all add-source
-- dependencies. It is initially populated by 'sandbox add-source' and kept
-- current by 'reinstallAddSourceDeps'. The user can install add-source deps
-- manually with 'cabal install' after having edited them, so we can err on the
-- side of caution sometimes.
-- FIXME: We should keep this info in the index file, together with build tree
-- refs.
timestampFileName :: FilePath
timestampFileName = "add-source-timestamps"

-- | Read the timestamp file. Returns an empty list if the file doesn't exist.
readTimestamps :: FilePath -> IO (Maybe [AddSourceTimestamp])
readTimestamps sandboxDir = do
  timestampString <- readFile timestampFile `catchIO` \_ -> return "[]"
  case reads timestampString of
    [(timestamps, s)] | all isSpace s -> return (Just timestamps)
    _                                 -> return Nothing
  where
    timestampFile = sandboxDir </> timestampFileName

-- | Write the timestamp file, atomically.
writeTimestamps :: FilePath -> [AddSourceTimestamp] -> IO ()
writeTimestamps sandboxDir timestamps = do
  writeFile  timestampTmpFile (show timestamps)
  renameFile timestampTmpFile timestampFile
  where
    timestampFile    = sandboxDir </> timestampFileName
    timestampTmpFile = timestampFile <.> "tmp"

-- | Given a list of 'AddSourceTimestamp's, a list of paths to add-source deps
-- we've reinstalled and a new timestamp value, update the timestamp value for
-- those deps. If there are new paths in the list, add them to the timestamp
-- file with the current date.
updateTimestamps :: EpochTime -> [AddSourceTimestamp] -> [FilePath]
                    -> [AddSourceTimestamp]
updateTimestamps newTimestamp timestamps paths =
  map (\p -> (p, newTimestamp)) newPaths ++ foldr updateTimestamp [] timestamps
  where
    oldPaths = map fst timestamps
    (pathsToUpdate, newPaths) = partition (flip elem oldPaths) paths

    updateTimestamp t@(path, _oldTimestamp) rest =
      if path `elem` pathsToUpdate
      then (path, newTimestamp) : rest
      else t : rest

-- | Given a list of 'AddSourceTimestamp's and a list of paths to add-source
-- deps we've removed, remove those deps from the list.
removeTimestamps :: [AddSourceTimestamp] -> [FilePath] -> [AddSourceTimestamp]
removeTimestamps l pathsToRemove = foldr removeTimestamp [] l
  where
    removeTimestamp t@(path, _oldTimestamp) rest =
      if path `elem` pathsToRemove
      then rest
      else t : rest

-- | Given an IO action that returns a list of build tree refs, remove those
-- build tree refs to the current time.
withRemoveTimestamps :: FilePath -> ([AddSourceTimestamp] -> IO [FilePath])<commit_msg>Replace a conditional with a guard.<commit_after>-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.Client.Sandbox.Timestamp
-- Maintainer  :  <EMAIL>
-- Portability :  portable
--
-- Timestamp file handling (for add-source dependencies).
-----------------------------------------------------------------------------

module Distribution.Client.Sandbox.Timestamp (
  AddSourceTimestamp,
  withRemoveTimestamps,
  withUpdateTimestamps,
  isDepModified,
  withModifiedDeps,
  ) where

import Control.Monad                                 (filterM, forM)
import Data.Char                                     (isSpace)
import Data.List                                     (partition)
import System.Directory                              (renameFile)
import System.FilePath                               (isAbsolute, (<.>), (</>))

import Distribution.PackageDescription               (BuildInfo (..),
                                                      Executable (..),
                                                      Library (..),
                                                      PackageDescription (..))
import Distribution.PackageDescription.Configuration (flattenPackageDescription)
import Distribution.PackageDescription.Parse         (readPackageDescription)
import Distribution.Simple.PreProcess                (knownSuffixHandlers)
import Distribution.Simple.SrcDist                   (allSourcesBuildInfo,
                                                      filterAutogenModule,
                                                      findIncludeFile,
                                                      findMainExeFile,
                                                      findSetupFile)
import Distribution.Simple.Utils                     (defaultPackageDesc, die,
                                                      findPackageDesc,
                                                      matchFileGlob)
import Distribution.Verbosity                        (Verbosity)

import Distribution.Client.Utils                     (inDir)

import Distribution.Compat.Exception                 (catchIO)
import Distribution.Compat.Time                      (EpochTime, getCurTime,
                                                      getModTime)


-- | Timestamp of an add-source dependency.
type AddSourceTimestamp = (FilePath, EpochTime)

-- | The 'add-source-timestamps' file keeps the timestamps of all add-source
-- dependencies. It is initially populated by 'sandbox add-source' and kept
-- current by 'reinstallAddSourceDeps'. The user can install add-source deps
-- manually with 'cabal install' after having edited them, so we can err on the
-- side of caution sometimes.
-- FIXME: We should keep this info in the index file, together with build tree
-- refs.
timestampFileName :: FilePath
timestampFileName = "add-source-timestamps"

-- | Read the timestamp file. Returns an empty list if the file doesn't exist.
readTimestamps :: FilePath -> IO (Maybe [AddSourceTimestamp])
readTimestamps sandboxDir = do
  timestampString <- readFile timestampFile `catchIO` \_ -> return "[]"
  case reads timestampString of
    [(timestamps, s)] | all isSpace s -> return (Just timestamps)
    _                                 -> return Nothing
  where
    timestampFile = sandboxDir </> timestampFileName

-- | Write the timestamp file, atomically.
writeTimestamps :: FilePath -> [AddSourceTimestamp] -> IO ()
writeTimestamps sandboxDir timestamps = do
  writeFile  timestampTmpFile (show timestamps)
  renameFile timestampTmpFile timestampFile
  where
    timestampFile    = sandboxDir </> timestampFileName
    timestampTmpFile = timestampFile <.> "tmp"

-- | Given a list of 'AddSourceTimestamp's, a list of paths to add-source deps
-- we've reinstalled and a new timestamp value, update the timestamp value for
-- those deps. If there are new paths in the list, add them to the timestamp
-- file with the current date.
updateTimestamps :: EpochTime -> [AddSourceTimestamp] -> [FilePath]
                    -> [AddSourceTimestamp]
updateTimestamps newTimestamp timestamps paths =
  map (\p -> (p, newTimestamp)) newPaths ++ foldr updateTimestamp [] timestamps
  where
    oldPaths = map fst timestamps
    (pathsToUpdate, newPaths) = partition (flip elem oldPaths) paths

    updateTimestamp t@(path, _oldTimestamp) rest
      | path `elem` pathsToUpdate = (path, newTimestamp) : rest
      | otherwise                 = t : rest

-- | Given a list of 'AddSourceTimestamp's and a list of paths to add-source
-- deps we've removed, remove those deps from the list.
removeTimestamps :: [AddSourceTimestamp] -> [FilePath] -> [AddSourceTimestamp]
removeTimestamps l pathsToRemove = foldr removeTimestamp [] l
  where
    removeTimestamp t@(path, _oldTimestamp) rest =
      if path `elem` pathsToRemove
      then rest
      else t : rest

-- | Given an IO action that returns a list of build tree refs, remove those
-- build tree refs to the current time.
withRemoveTimestamps :: FilePath -> ([AddSourceTimestamp] -> IO [FilePath])
{'fraction_non_alphanumeric': 0.10328915071183112, 'fraction_numerical': 0.0, 'mean_word_length': 1.8184836745987825, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 50, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4362593', 'n_tokens_mistral': 2315, 'n_tokens_neox': 2263, 'n_words': 768}