<commit_before>module Util (
    capitalize,
    capitalizePath,
    lowercase,
    camelcase,
    ensureSinglePath,
    tmpFname,
    backupFname,
    renameWithBackup
) where

import Control.Monad (when)
import System.IO.Error (isDoesNotExistError, catchIOError)
import Data.Time.Clock (getCurrentTime, diffUTCTime, NominalDiffTime)
import Control.Applicative ((<$>), (<*>))
import Data.String.Utils (join, split)
import Data.Char (toUpper, toLower)
import System.Directory (
    renameFile,
    copyFile,
    getModificationTime,
    doesFileExist)
import System.FilePath.Posix (
    joinPath,
    splitPath,
    takeDirectory,
    takeBaseName)


lowercase :: String -> String
lowercase word = map toLower word

capitalize :: String -> String
capitalize word = case word of
    [] -> []
    (x:xs) -> toUpper x:map toLower xs

capitalizePath :: FilePath -> FilePath
capitalizePath path =
    joinPath $ map capitalize $ splitPath path

camelcase :: String -> String
camelcase str =
    let xs = split "_" str in
    join "" $ lowercase (head xs) : (map capitalize $ tail xs)

ensureSinglePath :: [FilePath] -> Maybe FilePath
ensureSinglePath paths =
    case paths of
        [x] -> Just x
        [] -> Nothing
        _ -> Nothing

renameWithBackup :: FilePath -> FilePath -> IO ()
renameWithBackup old new = do
    -- Do not create backup of destination file
    -- if it has been modified withing the last 3 seconds
    recentlyModified <- fileRecentlyModified new 3
    when (not recentlyModified) $ copyFile new (backupFname new)
    renameFile old new

fileRecentlyModified :: FilePath -> NominalDiffTime -> IO Bool
fileRecentlyModified p s =
    (fmap (< s) $ diffUTCTime <$> getCurrentTime <*> getModificationTime p)
    `catchIOError` \e ->
        if isDoesNotExistError e
            then return False
            else ioError e

tmpFname :: FilePath -> FilePath
tmpFname path =
    joinPath [
        takeDirectory path,
        "." ++ takeBaseName path ++ ".new"
    ]

backupFname :: FilePath -> FilePath
backupFname path =
    joinPath [
        takeDirectory path,
        "." ++ takeBaseName path ++ ".old"
    ]
<commit_msg>Preserve extension<commit_after>module Util (
    capitalize,
    capitalizePath,
    lowercase,
    camelcase,
    ensureSinglePath,
    tmpFname,
    backupFname,
    renameWithBackup
) where

import Control.Monad (when)
import System.IO.Error (isDoesNotExistError, catchIOError)
import Data.Time.Clock (getCurrentTime, diffUTCTime, NominalDiffTime)
import Control.Applicative ((<$>), (<*>))
import Data.String.Utils (join, split)
import Data.Char (toUpper, toLower)
import System.Directory (
    renameFile,
    copyFile,
    getModificationTime,
    doesFileExist)
import System.FilePath.Posix (
    joinPath,
    splitPath,
    takeDirectory,
    takeBaseName,
    takeExtension)


lowercase :: String -> String
lowercase word = map toLower word

capitalize :: String -> String
capitalize word = case word of
    [] -> []
    (x:xs) -> toUpper x:map toLower xs

capitalizePath :: FilePath -> FilePath
capitalizePath path =
    joinPath $ map capitalize $ splitPath path

camelcase :: String -> String
camelcase str =
    let xs = split "_" str in
    join "" $ lowercase (head xs) : (map capitalize $ tail xs)

ensureSinglePath :: [FilePath] -> Maybe FilePath
ensureSinglePath paths =
    case paths of
        [x] -> Just x
        [] -> Nothing
        _ -> Nothing

renameWithBackup :: FilePath -> FilePath -> IO ()
renameWithBackup old new = do
    -- Do not create backup of destination file
    -- if it has been modified withing the last 3 seconds
    recentlyModified <- fileRecentlyModified new 3
    when (not recentlyModified) $ copyFile new (backupFname new)
    renameFile old new

fileRecentlyModified :: FilePath -> NominalDiffTime -> IO Bool
fileRecentlyModified p s =
    (fmap (< s) $ diffUTCTime <$> getCurrentTime <*> getModificationTime p)
    `catchIOError` \e ->
        if isDoesNotExistError e
            then return False
            else ioError e

tmpFname :: FilePath -> FilePath
tmpFname path =
    joinPath [
        takeDirectory path,
        join "" [".", takeBaseName path, "_tmp", takeExtension path]
    ]

backupFname :: FilePath -> FilePath
backupFname path =
    joinPath [
        takeDirectory path,
        join "" [".", takeBaseName path, "_bk", takeExtension path]
    ]

{'fraction_non_alphanumeric': 0.09498741130693522, 'fraction_numerical': 0.0009155413138017853, 'mean_word_length': 3.0425531914893615, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4339228', 'n_tokens_mistral': 1319, 'n_tokens_neox': 1291, 'n_words': 396}